All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.exigen.ie.constrainer.impl.IntExpRangeViolation Maven / Gradle / Ivy

package com.exigen.ie.constrainer.impl;
import com.exigen.ie.constrainer.EventOfInterest;
import com.exigen.ie.constrainer.Failure;
import com.exigen.ie.constrainer.IntExp;
import com.exigen.ie.constrainer.IntVar;
import com.exigen.ie.constrainer.Observer;
import com.exigen.ie.constrainer.Subject;

///////////////////////////////////////////////////////////////////////////////
/*
 * Copyright Exigen Group 1998, 1999, 2000
 * 320 Amboy Ave., Metuchen, NJ, 08840, USA, www.exigengroup.com
 *
 * The copyright to the computer program(s) herein
 * is the property of Exigen Group, USA. All rights reserved.
 * The program(s) may be used and/or copied only with
 * the written permission of Exigen Group
 * or in accordance with the terms and conditions
 * stipulated in the agreement/contract under which
 * the program(s) have been supplied.
 */
///////////////////////////////////////////////////////////////////////////////

/**
 * An implementation of the expression:
 * ((IntExp less rangeMin)*(rangeMin - IntExp) + (IntExp more rangeMax)*(IntExp - rangeMax)).
 */
public final class IntExpRangeViolation extends IntExpImpl
{
  private IntExp	 _exp;
  private int      _rangeMin, _rangeMax;
  private Observer _observer;

  private IntVar _domain;

  class ExpRangeViolationObserver extends Observer
  {
    public void update(Subject exp, EventOfInterest event)
      throws Failure
    {
      _domain.setMin(calc_min());
      _domain.setMax(calc_max());
//      propagate(); //???
    }

    public String toString()
    {
      return "ExpRangeViolationObserver: ";
    }

    public Object master()
    {
      return IntExpRangeViolation.this;
    }

    public int subscriberMask()
    {
      return MIN | MAX | VALUE;
    }

  } //~ ExpRangeViolationObserver


  public IntExpRangeViolation(IntExp exp, int rangeMin, int rangeMax)
  {
    super(exp.constrainer());

    _exp = exp;
    _rangeMin = rangeMin;
    _rangeMax = rangeMax;

    if(constrainer().showInternalNames())
    {
//      _name = "("+exp.name()+" in "+domainToString(rangeMin,rangeMax)+")";
      _name = "("+"("+exp.name()+"<"+rangeMin+")*("+rangeMin+"-"+exp.name()+")+"+
                  "("+exp.name()+">"+rangeMax+")*("+exp.name()+"-"+rangeMax+")"+")";
    }

//    int trace = IntVarImplTrace.TRACE_ALL;
    int trace = 0;
    _domain = constrainer().addIntVarTraceInternal(calc_min(), calc_max(), _name, IntVar.DOMAIN_PLAIN, trace);

    _exp.attachObserver(_observer = new ExpRangeViolationObserver());
  }

  public void attachObserver(Observer observer)
  {
    super.attachObserver(observer);
    _domain.attachObserver(observer);
  }

  public void reattachObserver(Observer observer)
  {
    super.reattachObserver(observer);
    _domain.reattachObserver(observer);
  }

  public void detachObserver(Observer observer)
  {
    super.detachObserver(observer);
    _domain.detachObserver(observer);
  }


  /**
   * Returns the value of the range violation at x.
   */
  int calc_v(int x)
  {
    if(x < _rangeMin)
      return _rangeMin - x;
    else if(x > _rangeMax)
      return x - _rangeMax;
    else
      return 0;
  }

  int calc_max()
  {
    // Max is at the one of the endpoints.
    return Math.max( calc_v(_exp.min()), calc_v(_exp.max()) );
    // Optimized?
//    return Math.max( Math.max(_rangeMin - _exp.min(), _exp.max() - _rangeMax), 0 );
  }

  int calc_min()
  {
    int expMin = _exp.min(), expMax = _exp.max();
    // exp >= _rangeMax
    if(expMin >= _rangeMax)
    {
      // v(xmin)
      return expMin - _rangeMax;
    }
    // exp <= _rangeMin
    else if(expMax <= _rangeMin)
    {
      // v(xmax)
      return _rangeMin - expMax;
    }
    else
    {
      return 0;
    }
  }

  public int max()
  {
    return _domain.max();
  }

  public int min()
  {
    return _domain.min();
  }

  public void setMax(int max) throws Failure
  {
//    System.out.println("+++IntExpRangeViolation.setMax(" +max + ") in " + this);

    if (max >= _domain.max())
      return;

    if (max < _domain.min())
      constrainer().fail("IntExpRangeViolation.setMax(): max < min()");

    _domain.setMax(max); // includes check for failure

    if(max < 0) // should be handled above
      abort("IntExpRangeViolation.setMax(): max < 0: " + max);

    _exp.setMin(_rangeMin-max);
    _exp.setMax(_rangeMax+max);

//    System.out.println("---IntExpRangeViolation.setMax(" +max + ") in " + this);
  }

  /**
   * Some expressions has to propagate their 'constraint domain'.
   */
  public void propagate() throws Failure
  {
    int min = _domain.min();
    int max = _domain.max();

    if(max >= 0)
    {
      _exp.setMin(_rangeMin-max);
      _exp.setMax(_rangeMax+max);
    }

    if(min > 0)
    {
      int holeMin = _rangeMin - min + 1;
      int holeMax = _rangeMax + min - 1;
      for(int i = holeMin; i <= holeMax; ++i)
        _exp.removeValue(i);
    }
  }

  public void setMin(int min) throws Failure
  {
//    System.out.println("+++IntExpRangeViolation.setMin(" +min + ") in " + this);

    if (min <= _domain.min())
      return;

    if (min > _domain.max())
      constrainer().fail("IntExpRangeViolation.setMin(): min > max()");

    _domain.setMin(min); // includes check for failure

    if(min <= 0) // should be handled above
      abort("IntExpRangeViolation.setMin(): min <= 0: " + min);

    int holeMin = _rangeMin - min + 1;
    int holeMax = _rangeMax + min - 1;
    for(int i = holeMin; i <= holeMax; ++i)
      _exp.removeValue(i);

//    System.out.println("---IntExpRangeViolation.setMin(" +min + ") in " + this);
  }

  public int value() throws Failure
  {
    return _domain.value();
  }

} // ~IntExpRangeViolation




© 2015 - 2024 Weber Informatics LLC | Privacy Policy