001package org.clafer.choco.constraint.propagator; 002 003import solver.constraints.Propagator; 004import solver.constraints.PropagatorPriority; 005import solver.exception.ContradictionException; 006import solver.variables.EventType; 007import solver.variables.IntVar; 008import solver.variables.SetVar; 009import solver.variables.Variable; 010import solver.variables.delta.monitor.SetDeltaMonitor; 011import util.ESat; 012import util.procedure.IntProcedure; 013 014/** 015 * Missing from the library. 016 * 017 * @author jimmy 018 */ 019public class PropIntNotMemberSet extends Propagator<Variable> { 020 021 private IntVar element; 022 private SetVar set; 023 private SetDeltaMonitor setD; 024 025 public PropIntNotMemberSet(IntVar element, SetVar set) { 026 super(new Variable[]{element, set}, PropagatorPriority.BINARY, true); 027 this.element = element; 028 this.set = set; 029 this.setD = set.monitorDelta(aCause); 030 } 031 032 private boolean isElementVar(int idx) { 033 return idx == 0; 034 } 035 036 private boolean isSetVar(int idx) { 037 return idx == 1; 038 } 039 040 @Override 041 public int getPropagationConditions(int vIdx) { 042 if (isElementVar(vIdx)) { 043 return EventType.INSTANTIATE.mask; 044 } 045 assert isSetVar(vIdx); 046 return EventType.ADD_TO_KER.mask; 047 } 048 049 @Override 050 public void propagate(int evtmask) throws ContradictionException { 051 for (int i = set.getKernelFirst(); i != SetVar.END; i = set.getKernelNext()) { 052 element.removeValue(i, aCause); 053 } 054 if (element.instantiated()) { 055 set.removeFromEnvelope(element.getValue(), aCause); 056 setPassive(); 057 } else if (set.instantiated()) { 058 setPassive(); 059 } 060 } 061 062 @Override 063 public void propagate(int idxVarInProp, int mask) throws ContradictionException { 064 if (isElementVar(idxVarInProp)) { 065 assert element.instantiated(); 066 set.removeFromEnvelope(element.getValue(), aCause); 067 setPassive(); 068 } else { 069 assert isSetVar(idxVarInProp); 070 setD.freeze(); 071 setD.forEach(pruneElementOnSetKer, EventType.ADD_TO_KER); 072 setD.unfreeze(); 073 if (element.instantiated()) { 074 set.removeFromEnvelope(element.getValue(), aCause); 075 setPassive(); 076 } else if (set.instantiated()) { 077 setPassive(); 078 } 079 } 080 } 081 private final IntProcedure pruneElementOnSetKer = new IntProcedure() { 082 083 @Override 084 public void execute(int setKer) throws ContradictionException { 085 element.removeValue(setKer, aCause); 086 } 087 }; 088 089 @Override 090 public ESat isEntailed() { 091 if (element.instantiated()) { 092 if (!set.envelopeContains(element.getValue())) { 093 return ESat.TRUE; 094 } 095 return set.instantiated() ? ESat.FALSE : ESat.UNDEFINED; 096 } 097 if (PropUtil.isDomSubsetKer(element, set)) { 098 return ESat.FALSE; 099 } 100 return PropUtil.isDomIntersectEnv(element, set) ? ESat.UNDEFINED : ESat.TRUE; 101 } 102 103 @Override 104 public String toString() { 105 return element + " not in " + set; 106 } 107}