@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); } } }
/** * Updates the lower bound of the domain of <code>this</code> to <code>value</code>. The * instruction comes from <code>propagator</code>. * * <ul> * <li>If <code>value</code> is smaller than the lower bound of the domain, nothing is done and * the return value is <code>false</code>, * <li>if updating the lower bound to <code>value</code> leads to a dead-end (domain wipe-out), * a <code>ContradictionException</code> is thrown, * <li>otherwise, if updating the lower bound to <code>value</code> can be done safely, the * event type is created (the original event can be promoted) and observers are notified and * the return value is <code>true</code> * </ul> * * @param value new lower bound (included) * @param cause updating releaser * @param informCause * @return true if the lower bound has been updated, false otherwise * @throws solver.exception.ContradictionException if the domain become empty due to this action */ public boolean updateLowerBound(int value, ICause cause, boolean informCause) throws ContradictionException { boolean change; ICause antipromo = cause; if (informCause) { cause = Cause.Null; } int old = this.getLB(); if (old < value) { if (this.getUB() < value) { solver.getExplainer().updateLowerBound(this, old, value, antipromo); this.contradiction(cause, MSG_LOW); } else { EventType e = EventType.INCLOW; int aValue = value - OFFSET; if (reactOnRemoval) { // BEWARE: this loop significantly decreases performances for (int i = old - OFFSET; i < aValue; i = VALUES.nextSetBit(i + 1)) { delta.add(i + OFFSET); } } VALUES.clear(old - OFFSET, aValue); LB.set(VALUES.nextSetBit(aValue)); int _size = SIZE.get(); int card = VALUES.cardinality(); SIZE.set(card); change = _size - card > 0; if (instantiated()) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } assert (change); this.notifyPropagators(e, cause); solver.getExplainer().updateLowerBound(this, old, value, antipromo); return change; } } 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 updateUpperBound(int value, ICause cause, boolean informCause) throws ContradictionException { ICause antipromo = cause; if (informCause) { cause = Cause.Null; } boolean change; int ub = this.getUB(); if (ub > value) { if (this.getLB() > value) { this.contradiction(cause, MSG_UPP); } else { EventType e = EventType.DECUPP; int aValue = value - OFFSET; // todo delta VALUES.clear(aValue + 1, ub - OFFSET + 1); ub = VALUES.prevSetBit(aValue) + OFFSET; UB.set(ub); int _size = SIZE.get(); int card = VALUES.cardinality(); SIZE.set(card); change = _size - card > 0; filterOnLeq(cause, ub); if (card == 1) { e = EventType.INSTANTIATE; if (cause.reactOnPromotion()) { cause = Cause.Null; } } this.notifyPropagators(e, cause); return change; } } return false; }
public BitsetXYSumView(IntVar a, IntVar b, Solver solver) { super(a, b, solver); int lbA = A.getLB(); int ubA = A.getUB(); int lbB = B.getLB(); int ubB = B.getUB(); OFFSET = lbA + lbB; VALUES = solver.getEnvironment().makeBitSet((ubA + ubB) - (lbA + lbB) + 1); DisposableRangeIterator itA = A.getRangeIterator(true); DisposableRangeIterator itB = B.getRangeIterator(true); while (itA.hasNext()) { itB.bottomUpInit(); while (itB.hasNext()) { VALUES.set(itA.min() + itB.min() - OFFSET, itA.max() + itB.max() - OFFSET + 1); itB.next(); } itB.dispose(); itA.next(); } itA.dispose(); SIZE.set(VALUES.cardinality()); }