import java.util.*; public class SelfDualModLattice extends ModLattice { public SelfDualModLattice(int initialSize, int [] inverse) { super(initialSize, inverse); } public boolean computeDual(Element e) //return value indicates if dual was successfully computed { Element answer; int alt; if (e.myTerm.op != 'v' && e.myTerm.op != '^') return true; //variables must have their duals already entered by hand answer = computeDual(e.myTerm); for (alt = 0; answer == null && alt < e.altsUsed; alt++) answer = computeDual(e.altTerms[alt]); if (answer == null) return false; if (e.dual == null) e.dual = answer; else identify(e.dual, answer); return true; } public void computeAllDuals() { for (int i = 0; i < elementCount; i++) computeDual(elements[i]); } private Element computeDual(Term aTerm) { Element e1 = aTerm.arg1.dual; Element e2 = aTerm.arg2.dual; if (e1 == null || e2 == null) return null; return (aTerm.op == 'v') ? meet(e1, e2) : join(e1, e2); } public void makeNewElements(int total) /* Fills squares in the table, creating new elements when necessary, until elementCount equals total. The only difference between this method and the parent method is the addition of the last instruction. */ { if (total <= elementCount) return; if (total > currentSize) { System.out.println ("Lattice can't hold that many elements."); return; } try { do { fillCurrentSquare(); updatePointer(); } while (total > elementCount); } catch(TableCompleteException e) { if (elementCount < total) System.out.println("Lattice completed with " + elementCount + " elements."); } computeAllConjugates(); computeAllDuals(); } //makeNewElements protected void preparation(char op, Element lhs, Element rhs, Vector elementResults) { Element conj1, conj2, conj, dual1, dual2, dual3; if (table[currentRow][currentColumn] != null) elementResults.addElement(table[currentRow][currentColumn]); for (int i = 0; i < auto; i++) { conj1 = lhs.conjugates[i]; conj2 = rhs.conjugates[i]; if (conj1 != null && conj2 != null) { conj = (op == 'v') ? join(conj1, conj2) : meet(conj1, conj2); if (conj != null && conj.conjugates[inverse[i]] != null) elementResults.addElement(conj.conjugates[inverse[i]]); } } dual1 = lhs.dual; dual2 = rhs.dual; if (dual1 != null && dual2 != null) { dual3 = (op == '^') ? join(dual1, dual2) : meet(dual1, dual2); if (dual3 != null && dual3.dual != null) elementResults.addElement(dual3.dual); } } protected Element makeNewElement(char op, Element lhs, Element rhs) { Element newElement = new Element(this, op, lhs, rhs); for (int i = 0; i < auto; i++) computeConjugate(newElement, i); computeDual(newElement); return newElement; } public ModLattice collapse(boolean keepAuto) { IntCell count = new IntCell(0); int [] repSet = myEqRel.repSet(count, elementCount); ModLattice theNewLattice; int [] lookup = repSet; //For each element number in the new lattice, //gives the corresponding number in the old lattice. Element [] lookup2 = new Element[elementCount]; //For each element number in the old //lattice, gives the corresponding element in the new lattice. Element oldElement, newElement; int oldConjugate, oldDual; Term oldTerm, newTerm; int [] currentClass; if (keepAuto) theNewLattice = new SelfDualModLattice(count.myInt, inverse); else theNewLattice = new ModLattice(count.myInt, new int[0]); //create elements of new lattice for (int i = 0; i < count.myInt; i++) { oldElement = elements[repSet[i]]; oldTerm = oldElement.myTerm; if (oldTerm.op == 'v' || oldTerm.op == '^') newTerm = new Term(oldTerm.op, lookup2[oldTerm.arg1.myNumber], lookup2[oldTerm.arg2.myNumber]); else newTerm = new Term(oldTerm.op); newElement = new Element(theNewLattice, newTerm); currentClass = myEqRel.classOf(oldElement.myNumber); for (int j = 0; j < currentClass.length; j++) lookup2[currentClass[j]] = newElement; if (keepAuto) { if (oldElement.dual != null) { oldDual = oldElement.dual.myNumber; newElement.dual = lookup2[oldDual]; } for (int j = 0; j < auto; j++) if (oldElement.conjugates[j] != null) { oldConjugate = oldElement.conjugates[j].myNumber; newElement.conjugates[j] = lookup2[oldConjugate]; } } for (int j = 0; j < oldElement.altsUsed; j++) { oldTerm = oldElement.altTerms[j]; if (oldTerm.op == 'v' || oldTerm.op == '^') newTerm = new Term(oldTerm.op, lookup2[oldTerm.arg1.myNumber], lookup2[oldTerm.arg2.myNumber]); else newTerm = new Term(oldTerm.op); newElement.addAlt(newTerm); } } // for (i) //fill table of new lattice for (int i = 0; i < theNewLattice.elementCount; i++) for (int j = 0; j < theNewLattice.elementCount; j++) { oldElement = table[lookup[i]][lookup[j]]; if (oldElement != null) { newElement = lookup2[oldElement.myNumber]; theNewLattice.table[i][j] = newElement; } } return theNewLattice; } //collapse } //class SelfDualModLattice