@Override public void backPropagate(int mask) throws ContradictionException { // one of the variable as changed externally, this involves a complete update of this if (!EventType.isRemove(mask)) { int elb = A.getLB() + B.getLB(); int eub = A.getUB() + B.getUB(); int ilb = LB.get(); int iub = UB.get(); int old_size = iub - ilb; // is == 0, then the view is already instantiated boolean up = false, down = false; EventType e = EventType.VOID; if (elb > ilb) { if (elb > iub) { this.contradiction(this, MSG_LOW); } VALUES.clear(ilb - OFFSET, elb - OFFSET); ilb = VALUES.nextSetBit(ilb - OFFSET) + OFFSET; LB.set(ilb); e = EventType.INCLOW; down = true; } if (eub < iub) { if (eub < ilb) { this.contradiction(this, MSG_LOW); } VALUES.clear(eub - OFFSET + 1, iub - OFFSET + 1); iub = VALUES.prevSetBit(iub - OFFSET + 1) + OFFSET; UB.set(iub); if (e != EventType.VOID) { e = EventType.BOUND; } else { e = EventType.DECUPP; } up = true; } int size = VALUES.cardinality(); SIZE.set(size); if (ilb > iub) { this.contradiction(this, MSG_EMPTY); } if (down || size == 1) { filterOnGeq(this, ilb); } if (up || size == 1) { // size == 1 means instantiation, then force filtering algo filterOnLeq(this, iub); } if (ilb == iub) { // size == 1 means instantiation, then force filtering algo if (old_size > 0) { notifyPropagators(EventType.INSTANTIATE, this); } } else { notifyPropagators(e, this); } } }
@Override public void backPropagate(int mask) throws ContradictionException { // one of the variable as changed externally, this involves a complete update of this // one of the variable as changed externally, this involves a complete update of this if (!EventType.isRemove(mask)) { int lA = A.getLB(), uA = A.getUB(); int lB = B.getLB(), uB = B.getUB(); int elb = Math.max(lA, lB); int eub = Math.max(uA, uB); int ilb = LB.get(); int iub = UB.get(); boolean change = false; EventType e = EventType.VOID; if (elb > ilb) { if (elb > iub) { this.contradiction(this, MSG_LOW); } SIZE.add(elb - ilb); ilb = elb; LB.set(ilb); e = EventType.INCLOW; change = true; } if (eub < iub) { if (eub < ilb) { this.contradiction(this, MSG_LOW); } SIZE.add(eub - iub); iub = eub; UB.set(iub); if (e != EventType.VOID) { e = EventType.BOUND; } else { e = EventType.DECUPP; } change |= true; } if (ilb > iub) { this.contradiction(this, MSG_EMPTY); } if (change) { if (ilb == iub) { notifyPropagators(EventType.INSTANTIATE, this); } else { notifyPropagators(e, this); } } } }
public MaxView(IntVar a, IntVar b, Solver solver) { super(a, b, solver); int lb = Math.max(A.getLB(), B.getLB()); int ub = Math.max(A.getUB(), B.getUB()); LB.set(lb); UB.set(ub); SIZE.set(ub - lb + 1); }
@Override public boolean removeValue(int value, ICause cause, boolean informCause) throws ContradictionException { ICause antipromo = cause; if (informCause) { cause = Cause.Null; } boolean change = false; int inf = getLB(); int sup = getUB(); if (value == inf && value == sup) { this.contradiction(cause, MSG_REMOVE); } else { if (inf <= value && value <= sup) { EventType e = EventType.REMOVE; int aValue = value - OFFSET; change = VALUES.get(aValue); this.VALUES.clear(aValue); if (change) { SIZE.add(-1); // todo delta } if (value == inf) { inf = VALUES.nextSetBit(aValue) + OFFSET; LB.set(inf); e = EventType.INCLOW; filterOnGeq(cause, inf); if (cause.reactOnPromotion()) { cause = Cause.Null; } } else if (value == sup) { sup = VALUES.prevSetBit(aValue) + OFFSET; UB.set(sup); e = EventType.DECUPP; filterOnLeq(cause, sup); if (cause.reactOnPromotion()) { cause = Cause.Null; } } if (change && !VALUES.isEmpty()) { if (this.instantiated()) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } this.notifyPropagators(e, cause); } else { if (VALUES.isEmpty()) { this.contradiction(cause, MSG_EMPTY); } } } } return change; }
@Override public boolean removeValue(int value, ICause cause, boolean informCause) throws ContradictionException { ICause antipromo = cause; if (informCause) { cause = Cause.Null; } int inf = getLB(); int sup = getUB(); if (value == inf && value == sup) { this.contradiction(cause, AbstractVariable.MSG_REMOVE); } else if (inf == value || value == sup) { EventType e; if (value == inf) { // todo: delta... LB.set(value + 1); e = EventType.INCLOW; if (cause.reactOnPromotion()) { cause = Cause.Null; } if (A.getLB() > B.getUB()) { A.updateLowerBound(value + 1, this, false); } if (B.getLB() > A.getUB()) { B.updateLowerBound(value + 1, this, false); } } else { // todo: delta... UB.set(value - 1); e = EventType.DECUPP; if (cause.reactOnPromotion()) { cause = Cause.Null; } A.updateUpperBound(value - 1, this, false); B.updateUpperBound(value - 1, this, false); } if (SIZE.get() > 0) { if (this.instantiated()) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } this.notifyPropagators(e, cause); } else if (SIZE.get() == 0) { this.contradiction(cause, MSG_EMPTY); } return true; } return false; }
@Override public boolean updateLowerBound(int value, ICause cause, boolean informCause) throws ContradictionException { ICause antipromo = cause; if (informCause) { cause = Cause.Null; } boolean change; int lb = this.getLB(); if (lb < value) { if (this.getUB() < value) { this.contradiction(cause, MSG_LOW); } else { EventType e = EventType.INCLOW; int aValue = value - OFFSET; // todo delta VALUES.clear(lb - OFFSET, aValue); lb = VALUES.nextSetBit(aValue) + OFFSET; LB.set(lb); int _size = SIZE.get(); int card = VALUES.cardinality(); SIZE.set(card); change = _size - card > 0; filterOnGeq(cause, lb); if (instantiated()) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } this.notifyPropagators(e, cause); return change; } } return false; }
@Override public boolean instantiateTo(int value, ICause cause, boolean informCause) throws ContradictionException { if (informCause) { cause = Cause.Null; } int lb = LB.get(); if (this.instantiated()) { if (value != lb) { this.contradiction(cause, MSG_EMPTY); } return false; } else if (contains(value)) { int aValue = value - OFFSET; // todo delta this.VALUES.clear(); this.VALUES.set(aValue); this.LB.set(value); this.UB.set(value); this.SIZE.set(1); if (VALUES.isEmpty()) { this.contradiction(cause, MSG_EMPTY); } filterOnLeq(cause, value); filterOnGeq(cause, value); this.notifyPropagators(EventType.INSTANTIATE, cause); return true; } else { this.contradiction(cause, MSG_UNKNOWN); return false; } }
@Override public boolean updateLowerBound(int aValue, ICause cause, boolean informCause) throws ContradictionException { ICause antipromo = cause; if (informCause) { cause = Cause.Null; } int old = this.getLB(); if (old < aValue) { if (this.getUB() < aValue) { this.contradiction(cause, MSG_LOW); } else { EventType e = EventType.INCLOW; // todo delta SIZE.add(old - aValue); LB.set(aValue); if (A.getLB() > B.getUB()) { A.updateLowerBound(aValue, this, false); } if (B.getLB() > A.getUB()) { B.updateLowerBound(aValue, this, false); } if (instantiated()) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } this.notifyPropagators(e, cause); return true; } } return false; }