import java.util.*;
import javax.swing.JComponent;
class grammar
{
public static final String UNKNOWN = "Unknown";
public static final String SATISFIED = "Satisfied";
public static final String VIOLATED = "Violated";
public static final String UNIT_OPEN = "Unit-open";
public static final String NON_UNIT_OPEN = "Non-unit-open";
// this is the set of selections that are to be propagated by
// an LTMS
static ArrayList UserSelections;
static ArrayList violated;
static ArrayList _originals;
private static boolean debugIsOn = false;
private static boolean updateNow = true;
private static boolean beginning = true;
static boolean store_originals = true;
grammar(String name)
{
UserSelections = new ArrayList();
violated = new ArrayList();
_originals = new ArrayList();
}
static void initDebugTable() // initialize debug table
{
if(beginning)
{ reset();
}
DebugTable.createAndShowGUI();
debugIsOn = true;
}
static void initFormulas() // initialize propagation formulas table
{
Formulas.createAndShowGUI();
}
static void propagate() // clear variables, and propagate UserSelections
{
beginning = false;
updateNow = false;
reset();
updateNow = true;
for(int i = 0; i < UserSelections.size(); i++)
{ variable v = (variable) (UserSelections.get(i));
v.value = variable.T;
v.explanation = "Set by user";
}
satisfyClauses();
if(debugIsOn)
{ // update debug table components
for(int row = 0; row < DebugTable.sortedVtable.length; row++)
{ variable v = (variable)(variable.Vtable.get(DebugTable.sortedVtable[row]));
if(v.value == variable.T)
{ DebugTable.data[row][1] = "True";
}
else if(v.value == variable.F)
{ DebugTable.data[row][1] = "False";
}
else // v.value == variable.U
{ DebugTable.data[row][1] = "Unknown";
}
if(v.userSet)
{ DebugTable.data[row][2] = "True";
}
else
{ DebugTable.data[row][2] = "False";
}
}
DebugTable.update();
}
if(violated.size() > 0)
{ JOptionPane.showMessageDialog(null,
"Violations occured",
"Invalid specification",
JOptionPane.ERROR_MESSAGE);
}
violated.clear();
store_originals = false;
}
public static void reset() // reset variables
{
Iterator vars = (variable.Vtable.values()).iterator();
while(vars.hasNext())
{ variable v = (variable)(vars.next());
v.value = variable.U;
v.userSet = true;
v.explanation = "";
}
String rootName = (grammar.rootProduction).name;
variable root = (variable) (variable.Vtable.get(rootName));
root.value = variable.T;
root.userSet = false;
root.explanation = "Root";
if(debugIsOn && updateNow)
{ // update debug table components
for(int row = 0; row < DebugTable.sortedVtable.length; row++)
{ variable v = (variable)(variable.Vtable.get(DebugTable.sortedVtable[row]));
if(rootName.equals(v.name))
{ DebugTable.data[row][1] = "True";
DebugTable.data[row][2] = "False";
}
else
{ DebugTable.data[row][1] = "Unknown";
DebugTable.data[row][2] = "True";
}
}
DebugTable.update();
}
}
private static void satisfyClauses()
{
Stack clauses = new Stack();
ArrayList nonUnit = new ArrayList();
int formulaIndex = 0;
// go through production formulas
Iterator i = (production.Ptable.values()).iterator();
while(i.hasNext())
{ production p = (production) (i.next());
if(store_originals)
{ _originals.add(p.formula.toString());
}
node temp = (p.formula).simplify().cnf();
if(temp instanceof and)
{ ArrayList formulas = new ArrayList();
splitFormula(formulas, temp);
for(int j = 0; j < formulas.size(); j++)
{ String _original = (String) _originals.get(formulaIndex);
clause c = new clause((node) formulas.get(j), null, _original);
checkClause(c, c.n);
// perform actions based on the value of c.
// if c.value == SATISFIED, then clause is already satisfied
if(VIOLATED.equals(c.value))
{ if(violated == null)
{ violated = new ArrayList();
}
violated.add(p.formula);
}
else if(UNKNOWN.equals(c.value))
{ if(c.unknowns == 1)
{ c.value = UNIT_OPEN;
clauses.push(c);
}
else // c.unknowns > 1
{ c.value = NON_UNIT_OPEN;
nonUnit.add(c);
}
}
}
}
else
{ String _original = (String) _originals.get(formulaIndex);
clause c = new clause(temp, null, _original);
checkClause(c, c.n);
// perform actions based on the value of c.
// if c.value == SATISFIED, then clause is already satisfied
if(VIOLATED.equals(c.value))
{ if(violated == null)
{ violated = new ArrayList();
}
violated.add(p.formula);
}
else if(UNKNOWN.equals(c.value))
{ if(c.unknowns == 1)
{ c.value = UNIT_OPEN;
clauses.push(c);
}
else // c.unknowns > 1
{ c.value = NON_UNIT_OPEN;
nonUnit.add(c);
}
}
}
formulaIndex++;
}
// go through pattern formulas
i = (pattern.Ttable.values()).iterator();
while(i.hasNext())
{ pattern p = (pattern) (i.next());
if(store_originals)
{ _originals.add(p.formula.toString());
}
node temp = (p.formula).simplify().cnf();
if(temp instanceof and)
{ ArrayList formulas = new ArrayList();
splitFormula(formulas, temp);
for(int j = 0; j < formulas.size(); j++)
{ String _original = (String) _originals.get(formulaIndex);
clause c = new clause((node) formulas.get(j), null, _original);
checkClause(c, c.n);
// perform actions based on the value of c.
// if c.value == SATISFIED, then clause is already satisfied
if(VIOLATED.equals(c.value))
{ violated.add(c.n);
}
else if(UNKNOWN.equals(c.value))
{ if(c.unknowns == 1)
{ c.value = UNIT_OPEN;
clauses.push(c);
}
else // c.unknowns > 1
{ c.value = NON_UNIT_OPEN;
nonUnit.add(c);
}
}
}
}
else
{ String _original = (String) _originals.get(formulaIndex);
clause c = new clause(temp, null, _original);
checkClause(c, c.n);
// perform actions based on the value of c.
// if c.value == SATISFIED, then clause is already satisfied
if(VIOLATED.equals(c.value))
{ violated.add(c.n);
}
else if(UNKNOWN.equals(c.value))
{ if(c.unknowns == 1)
{ c.value = UNIT_OPEN;
clauses.push(c);
}
else // c.unknowns > 1
{ c.value = NON_UNIT_OPEN;
nonUnit.add(c);
}
}
}
formulaIndex++;
}
// go through additional constraints
for(int k = 0; k < ESList.CTable.size(); k++)
{ node p = (node) (ESList.CTable.get(k));
if(store_originals)
{ _originals.add(p.toString());
}
node temp = p.simplify().cnf();
if(temp instanceof and)
{ ArrayList formulas = new ArrayList();
splitFormula(formulas, temp);
for(int j = 0; j < formulas.size(); j++)
{ String _original = (String) _originals.get(formulaIndex);
clause c = new clause((node) formulas.get(j), null, _original);
checkClause(c, c.n);
// perform actions based on the value of c.
// if c.value == SATISFIED, then clause is already satisfied
if(VIOLATED.equals(c.value))
{ violated.add(c.n);
}
else if(UNKNOWN.equals(c.value))
{ if(c.unknowns == 1)
{ c.value = UNIT_OPEN;
clauses.push(c);
}
else // c.unknowns > 1
{ c.value = NON_UNIT_OPEN;
nonUnit.add(c);
}
}
}
}
else
{ String _original = (String) _originals.get(formulaIndex);
clause c = new clause(temp, null, _original);
checkClause(c, c.n);
// perform actions based on the value of c.
// if c.value == SATISFIED, then clause is already satisfied
if(VIOLATED.equals(c.value))
{ violated.add(c.n);
}
else if(UNKNOWN.equals(c.value))
{ if(c.unknowns == 1)
{ c.value = UNIT_OPEN;
clauses.push(c);
}
else // c.unknowns > 1
{ c.value = NON_UNIT_OPEN;
nonUnit.add(c);
}
}
}
formulaIndex++;
}
// propagate constraints
while(true)
{ boolean changed = false;
while(!clauses.empty())
{ clause c = (clause) clauses.pop();
c.value = null;
c.unknowns = 0;
checkClause(c, c.n);
// if c.value == SATISFIED, then nothing else needs to be done
// on the clause
if(UNKNOWN.equals(c.value))
{ setTerm(c, c.n);
c.value = null;
c.unknowns = 0;
checkClause(c, c.n);
if(VIOLATED.equals(c.value))
{ violated.add(c.n);
}
}
else if(VIOLATED.equals(c.value))
{ violated.add(c.n);
}
}
for(int j = 0; j < nonUnit.size(); j++)
{ clause c = (clause) nonUnit.get(j);
c.value = null;
c.unknowns = 0;
checkClause(c, c.n);
if(c.unknowns == 1)
{ c.value = UNIT_OPEN;
nonUnit.remove(j);
j--;
clauses.push(c);
changed = true;
}
else // c.unknowns > 1
{ c.value = NON_UNIT_OPEN;
}
}
if(!changed)
{ break;
}
}
}
static void splitFormula(ArrayList formulas, node n)
{
if(n.left != null)
{ if(n.left instanceof and)
{ splitFormula(formulas, n.left);
}
else
{ formulas.add(n.left);
}
}
if(n.right != null)
{ if(n.right instanceof and)
{ splitFormula(formulas, n.right);
}
else
{ formulas.add(n.right);
}
}
}
static void checkClause(clause c, node n)
{
if(n instanceof bterm)
{ variable v = (variable) (variable.Vtable.get(n.toString()));
if(v.value == variable.T)
{ c.value = SATISFIED;
}
else if(v.value == variable.F)
{ if(c.value == null)
{ c.value = VIOLATED;
}
}
else // v.value == variable.U
{ if(!SATISFIED.equals(c.value))
{ c.value = UNKNOWN;
(c.unknowns)++;
}
}
}
else if(n instanceof not)
{ if(n.left != null)
{ variable v = (variable) (variable.Vtable.get((n.left).toString()));
if(v.value == variable.T)
{ if(c.value == null)
{ c.value = VIOLATED;
}
}
else if(v.value == variable.F)
{ c.value = SATISFIED;
}
else // v.value == variable.U
{ if(!SATISFIED.equals(c.value))
{ c.value = UNKNOWN;
(c.unknowns)++;
}
}
}
}
else // n instanceof or
{ if(n.left != null)
{ checkClause(c, n.left);
}
if(n.right != null)
{ checkClause(c, n.right);
}
}
}
private static void setTerm(clause c, node n)
{
if(n instanceof bterm)
{ variable v = (variable) (variable.Vtable.get(n.toString()));
if(v.value == variable.U)
{ v.value = variable.T;
v.userSet = false;
StringBuffer expl = new StringBuffer("");
int edit = expl.length();
buildExplanation(v.name, c.n, expl);
String temp = expl.toString();
if(temp.length() == edit) // no assumptions
{ v.explanation = c._original.toString();
}
else // take out last comma
{ temp = temp.substring(0, temp.length() - 2);
v.explanation = temp + " and " + c._original.toString();
}
}
}
else if(n instanceof not)
{ if(n.left != null)
{ variable v = (variable) (variable.Vtable.get((n.left).toString()));
if(v.value == variable.U)
{ v.value = variable.F;
v.userSet = false;
StringBuffer expl = new StringBuffer("");
int edit = expl.length();
buildExplanation(v.name, c.n, expl);
String temp = expl.toString();
if(temp.length() == edit) // no assumptions
{ v.explanation = c._original.toString();
}
else // take out last comma
{ temp = temp.substring(0, temp.length() - 2);
v.explanation = temp + " and " + c.__original.toString();
}
}
}
}
else // n instanceof or
{ if(n.left != null)
{ setTerm(c, n.left);
}
if(n.right != null)
{ setTerm(c, n.right);
}
}
}
private static void buildExplanation(String name, node n, StringBuffer expl)
{
if(n instanceof bterm)
{ variable v = (variable) (variable.Vtable.get(n.toString()));
// no need to include the variable in its own explanation
if(name.equals(v.name))
{ return;
}
if(v.value == variable.T)
{ expl.append(v.name + "=true, ");
}
else if(v.value == variable.F)
{ expl.append(v.name + "=false, ");
}
else // v.value == variable.U
{ expl.append(v.name + "=unknown, ");
}
}
else if(n instanceof not)
{ if(n.left != null)
{ variable v = (variable) (variable.Vtable.get((n.left).toString()));
// no need to include the variable in its own explanation
if(name.equals(v.name))
{ return;
}
if(v.value == variable.T)
{ expl.append(v.name + "=true, ");
}
else if(v.value == variable.F)
{ expl.append(v.name + "=false, ");
}
else // v.value == variable.U
{ expl.append(v.name + "=unknown, ");
}
}
}
else // n instanceof or
{ if(n.left != null)
{ buildExplanation(name, n.left, expl);
}
if(n.right != null)
{ buildExplanation(name, n.right, expl);
}
}
}
}