예제 #1
0
  /**
   * 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;
    }
  }
예제 #2
0
  /**
   * 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;
  }
예제 #3
0
  /**
   * 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;
  }