/** * Instantiates the domain of <code>this</code> to <code>value</code>. The instruction comes from * <code>propagator</code>. * * <ul> * <li>If the domain of <code>this</code> is already instantiated to <code>value</code>, nothing * is done and the return value is <code>false</code>, * <li>If the domain of <code>this</code> is already instantiated to another value, then a * <code>ContradictionException</code> is thrown, * <li>Otherwise, the domain of <code>this</code> is restricted to <code>value</code> and the * observers are notified and the return value is <code>true</code>. * </ul> * * @param value instantiation value (int) * @param cause instantiation releaser * @param informCause * @return true if the instantiation is done, false otherwise * @throws solver.exception.ContradictionException if the domain become empty due to this action */ public boolean instantiateTo(int value, ICause cause, boolean informCause) throws ContradictionException { // BEWARE: THIS CODE SHOULD NOT BE MOVED TO THE DOMAIN TO NOT DECREASE PERFORMANCES! solver .getExplainer() .instantiateTo( this, value, cause); // the explainer is informed before the actual instantiation is performed if (informCause) { cause = Cause.Null; } if (this.instantiated()) { if (value != this.getValue()) { this.contradiction(cause, MSG_INST); } return false; } else if (contains(value)) { int aValue = value - OFFSET; if (reactOnRemoval) { int i = VALUES.nextSetBit(this.LB.get()); for (; i < aValue; i = VALUES.nextSetBit(i + 1)) { delta.add(i + OFFSET); } i = VALUES.nextSetBit(aValue + 1); for (; i >= 0; i = VALUES.nextSetBit(i + 1)) { delta.add(i + OFFSET); } } this.VALUES.clear(); this.VALUES.set(aValue); this.LB.set(aValue); this.UB.set(aValue); this.SIZE.set(1); if (VALUES.isEmpty()) { this.contradiction(cause, MSG_EMPTY); } this.notifyPropagators(EventType.INSTANTIATE, cause); return true; } else { this.contradiction(cause, MSG_UNKNOWN); return false; } }
/** * 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; }
/** * Removes <code>value</code>from the domain of <code>this</code>. The instruction comes from * <code>propagator</code>. * * <ul> * <li>If <code>value</code> is out of the domain, nothing is done and the return value is * <code>false</code>, * <li>if removing <code>value</code> leads to a dead-end (domain wipe-out), a <code> * ContradictionException</code> is thrown, * <li>otherwise, if removing <code>value</code> from the domain 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 value to remove from the domain (int) * @param cause removal releaser * @param informCause * @return true if the value has been removed, false otherwise * @throws solver.exception.ContradictionException if the domain become empty due to this action */ public boolean removeValue(int value, ICause cause, boolean informCause) throws ContradictionException { // BEWARE: THIS CODE SHOULD NOT BE MOVED TO THE DOMAIN TO NOT DECREASE PERFORMANCES! boolean change = false; ICause antipromo = cause; if (informCause) { cause = Cause.Null; } int inf = getLB(); int sup = getUB(); if (value == inf && value == sup) { solver.getExplainer().removeValue(this, value, antipromo); 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.set(aValue, false); if (change) { this.SIZE.add(-1); if (reactOnRemoval) { delta.add(aValue + OFFSET); } } if (value == inf) { LB.set(VALUES.nextSetBit(aValue)); e = EventType.INCLOW; if (cause.reactOnPromotion()) { cause = Cause.Null; } } else if (value == sup) { UB.set(VALUES.prevSetBit(aValue)); e = EventType.DECUPP; 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()) { solver.getExplainer().removeValue(this, value, antipromo); this.contradiction(cause, MSG_EMPTY); } } } } if (change) { solver.getExplainer().removeValue(this, value, antipromo); } return change; }