public Goal execute() throws Failure {
    _exp1.setMax(_exp2.max() - _offset); // may fail
    _exp1.attachObserver(new ObserverExp1Min());

    _exp2.setMin(_exp1.min() + _offset); // may fail
    _exp2.attachObserver(new ObserverExp2Max());
    return null;
  }
  public Goal execute() throws Failure {
    class ObserverExpNotValue extends Observer {
      @Override
      public Object master() {
        return ConstraintExpNotValue.this;
      }

      @Override
      public int subscriberMask() {
        return EventOfInterest.VALUE;
      }

      @Override
      public String toString() {
        return "ObserverExpNotValue:" + _exp.name() + "!=" + _value;
      }

      @Override
      public void update(Subject exp, EventOfInterest interest) throws Failure {
        // Debug.print("ObserverExpNotValue("+_exp+") "+interest);
        int value = ((IntEvent) interest).min();
        if (value == _value) {
          // constrainer().fail("attempt to set a removed value
          // "+value+" for "+exp);
          constrainer().fail();
        }
      }
    } // ~ ObserverExpNotValue

    if (_value == _exp.max()) {
      _exp.setMax(_value - 1);
    } else if (_value == _exp.min()) {
      _exp.setMin(_value + 1);
    } else {
      // Debug.print("attach ObserverExpNotValue("+_exp+","+_value+")");
      _exp.attachObserver(new ObserverExpNotValue());
    }

    return null;
  }