//package um.threevar.BAC; import choco.*; import choco.integer.*; import choco.integer.constraints.*; import choco.util.*; //See separate specification file for justification of the algorithm. public class BACUM extends AbstractTernIntConstraint { private class Triple { IntDomainVar s, m, l; public Triple(IntDomainVar s, IntDomainVar m, IntDomainVar l) { this.s = s; this.m = m; this.l = l; } } private boolean debug; //true iff debug messages are wanted public BACUM(IntDomainVar v0, IntDomainVar v1, IntDomainVar v2, boolean debug) { super(v0, v1, v2); this.debug = debug; } //return true if and only if v and w's domains have null intersection private static boolean nullIntersection(IntDomainVar v, IntDomainVar w) { return v.getInf() > w.getSup() || v.getSup() < w.getInf(); } //return triple of variables ordered by infimum. Uses sorting algorithm for //3 items using at most 3 comparisons, see page 173 of CLR Introduction to //Algorithms. private Triple sortOnInf() { int v0Inf = v0.getInf(); int v1Inf = v1.getInf(); int v2Inf = v2.getInf(); if(v0Inf <= v1Inf) if(v1Inf <= v2Inf) return new Triple(v0, v1, v2); else if(v0Inf <= v2Inf) return new Triple(v0, v2, v1); else return new Triple(v2, v0, v1); else if(v0Inf <= v2Inf) return new Triple(v1, v0, v2); else if(v1Inf <= v2Inf) return new Triple(v1, v2, v0); else return new Triple(v2, v1, v0); } private Triple sortOnSup() { int v0Sup = v0.getSup(); int v1Sup = v1.getSup(); int v2Sup = v2.getSup(); if(v0Sup <= v1Sup) if(v1Sup <= v2Sup) return new Triple(v0, v1, v2); else if(v0Sup <= v2Sup) return new Triple(v0, v2, v1); else return new Triple(v2, v0, v1); else if(v0Sup <= v2Sup) return new Triple(v1, v0, v2); else if(v1Sup <= v2Sup) return new Triple(v1, v2, v0); else return new Triple(v2, v1, v0); } //called whenever an inf is changed public void awakeOnInf(int idx) throws ContradictionException { if(debug) System.out.println("awakeOnInf(" + idx + ")"); fixBounds(); if(debug) System.out.println("awakeOnInf() ends"); } //called whenever a sup is changed public void awakeOnSup(int idx) throws ContradictionException { if(debug) System.out.println("awakeOnSup(" + idx + ")"); fixBounds(); if(debug) System.out.println("awakeOnSup() ends"); } //initial propagation, just check uppers and lowers public void awake() throws ContradictionException { if(debug) System.out.println("awake()"); fixBounds(); if(debug) System.out.println("awake() ends"); } public void awakeOnRem(int idx, int x) throws ContradictionException { if(debug) System.out.println("awakeOnRem(" + idx + "," + x + ")"); } public void awakeOnRemovals(int idx, IntIterator deltaDom) throws ContradictionException { if(debug) System.out.println("awakeOnRemovals(" + idx + ")"); } public void propagate() throws ContradictionException { if(debug) System.out.println("propagate()"); } public boolean isSatisfied() { return true; } //when variable index is instantiated, just check both bounds public void awakeOnInst(int idx) throws ContradictionException { if(debug) { IntDomainVar theVar = (idx == 0 ? v0 : (idx == 1 ? v1 : v2)); System.out.println("awakeOnInst(" + idx + ")"); System.out.println("setting to " + theVar.getVal()); } fixBounds(); if(debug) System.out.println("awakeOnInst() ends"); } public void fixBounds() throws ContradictionException { if(debug) { System.out.println("fixBounds()"); System.out.println("vars: " + v0.pretty() + " " + v1.pretty() + " " + v2.pretty()); } //FIX UP THE INFS Triple si = sortOnInf(); int sInf = si.s.getInf(); int mInf = si.m.getInf(); int lInf = si.l.getInf(); //first case, each inf is different if(sInf != mInf && mInf != lInf) { if(debug) System.out.println("case 1: infs all different:"); si.s.setInf(mInf); //4th case, action is identical to first case but temporarily //separated for clarity } else if(mInf == lInf && sInf != mInf) { if(debug) System.out.println("case 4: smallest inf is distinct:"); si.s.setInf(mInf); } //FIX UP THE SUPS Triple ss = sortOnSup(); int sSup = ss.s.getSup(); int mSup = ss.m.getSup(); int lSup = ss.l.getSup(); //first case, each sup is different if(sSup != mSup && mSup != lSup) { if(debug) System.out.println("case 1: sups all different"); if(nullIntersection(ss.l, ss.s)) { if(debug) System.out.println("null intersection of s and l"); ss.m.setSup(sSup); } else if(nullIntersection(ss.m, ss.s)) { if(debug) System.out.println("null intersection of m and l"); ss.l.setSup(sSup); } //third case, largest are equal but smallest is different } else if (sSup != mSup && mSup == lSup) { if(debug) System.out.println("case 3: 2 largest sups are equal"); if(nullIntersection(ss.m, ss.s)) { if(debug) System.out.println("null intersection of s and m"); ss.l.setSup(sSup); } else if(nullIntersection(ss.l, ss.s)) { if(debug) System.out.println("null intersection of s and l"); ss.m.setSup(sSup); } } if(debug) { System.out.println("end vars: " + v0.pretty() + " " + v1.pretty() + " " + v2.pretty()); System.out.println("fixBounds() ends"); } } }