Package com.exigen.ie.constrainer

Source Code of com.exigen.ie.constrainer.ObserverTraceVars

package com.exigen.ie.constrainer;

///////////////////////////////////////////////////////////////////////////////
/*
* 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.
*/
///////////////////////////////////////////////////////////////////////////////
import java.io.PrintStream;
import java.io.Serializable;

import com.exigen.ie.constrainer.impl.ConstraintAllDiff;
import com.exigen.ie.constrainer.impl.ExpressionFactoryImpl;
import com.exigen.ie.constrainer.impl.FloatVarImpl;
import com.exigen.ie.constrainer.impl.FloatVarImplTrace;
import com.exigen.ie.constrainer.impl.GoalStack;
import com.exigen.ie.constrainer.impl.IntBoolVarImpl;
import com.exigen.ie.constrainer.impl.IntExpCardIntExp;
import com.exigen.ie.constrainer.impl.IntSetVarImpl;
import com.exigen.ie.constrainer.impl.IntVarImpl;
import com.exigen.ie.constrainer.impl.IntVarImplTrace;
import com.exigen.ie.constrainer.impl.UndoFastVectorAdd;
import com.exigen.ie.constrainer.impl.UndoStack;
import com.exigen.ie.constrainer.impl.UndoableFloatImpl;
import com.exigen.ie.constrainer.impl.UndoableIntImpl;
import com.exigen.ie.constrainer.impl.UndoableOnceImpl;
import com.exigen.ie.tools.FastQueue;
import com.exigen.ie.tools.FastStack;
import com.exigen.ie.tools.FastVector;
import com.exigen.ie.tools.RTExceptionWrapper;

/**
* An implementation of the Constrainer - a placeholder for all variables,
* constraints, and search goals of the problem.
* <p>
* The Constrainer is a Java package for modeling and solving different
* constraint satisfaction problems.
*
* A problem is represented in terms of the decision variables and constraints,
* which define relationships between these variables.
*
* The decision variables could be represented in form of Java objects which may
* use the predefined constrained variables such as IntVar.
*
* The constraints themselves are objects inherited from a generic class
* Constraint.
*
* A user can define new business constraints.
*
* <p>
* To find the problem solutions, the search algorithms could be represented
* using objects called Goals as building blocks. The Constrainer supports a
* reversible environment with multiple choice points: when constraints/goals
* fail, the Constrainer automatically backtracks to a previous choice point (if
* any).
* <p>
* There are several basic entities in the Constrainer:
* <ol>
* <li> Class Constrainer - a placeholder for all variables, constraints, and
* search goals of the problem
* <li> Interface Subject - a base-class for constrained variables. Contains the
* major methods to allow constraints (observers) observe the modification of
* the variables (subjects).
* <li> Interface IntVar - constrained integer variables, the most popular
* subclass of the class Subject
* <li> Interface Goal - a base class for different search goals and
* constraints.
* </ol>
*
* @see Goal
* @see IntVar
* @see FloatVar
* @see Subject
* @author (C)2000 Exigen Group (http://www.IntelEngine.com)
*/

/*
* Implementation notes
*
* GOALS EXECUTION. There are two major stacks: execution stack "EXE" and
* alternative stack "ALT". At each choice point we create a new reversibility
* stack "REV". EXE.push(goal); while(!EXE.empty()) { execute(EXE.pop()); Goal
* execution could: - push new subgoal on EXE (GoalAnd) - push goals on ALT
* (GoalOr) - fail. When failed: - pop from EXE all goals pushed on it after the
* last choice point (done via marker) - if ALT.empty, FAILURE! -
* EXE.push(ALT.pop()) } SUCCESS!
*
*/

public final class Constrainer implements Serializable {
  static public final double FLOAT_MAX = 1.79769313486231570815e+308; // IEEE
                                    // 754
  static public final double FLOAT_MIN = 2.225073858507202e-308; // the
                                  // smallest
                                  // positive
                                  // IEEE 754

  static public final int INT_MAX = 2147483647;
  static public final int INT_MIN = -2147483647 - 1;

  static public double FLOAT_PRECISION = 1.0e-6;

  // PRIVATE MEMBERS
  private String _name;
  private int _labelsCounter;
  private FastVector _intvars;
  private FastVector _floatvars;
  private FastVector _intsetvars;
  private FastVector _constraints;
  // private FastVector _goals;

  private int _choice_point = 0;

  // private FastStack _execution_stack;
  // private FastStack _alternative_stack;
  private GoalStack _goal_stack;

  // private FastStack _reversibility_stack;
  private UndoStack _reversibility_stack;

  private int _number_of_choice_points = 0;
  private int _number_of_failures = 0;
  private int _number_of_undos = 0;
  private long _time_limit = 0; // in milliseconds (0-no limit)
  private boolean _time_limit_exceeded = false; // == Changed: added by OR
  private long _failures_limit = 0; // in failures (0-no limit)
  static private double _precision = 1e-6;
  private FastVector _choice_point_objects;
  // private Failure _failure;
  private FastVector _failure_objects;
  private boolean _trace_failure_stack;

  private int _failure_display_frequency;
  private FastVector _backtrack_objects;

  // private Goal _goal_CP_marker;
  // private Undo _undo_CP_marker;
  // private Goal _restore_goal;
  // private Goal _save_goal;

  private boolean _trace_goals;

  // private ReusableFactory _undo_subject_factory;

  private boolean _show_internal_names;
  private boolean _show_variable_names;

  private long _initial_memory;
  private long _max_occupied_memory;
  private long _number_of_notifications;

  private boolean _print_information;
  private long _execution_time = 0;

  private FastQueue _propagation_queue;
  // private FastStack _propagation_queue;

  // private EventOfInterest _current_event_of_interest;

  private ExpressionFactory _expressionFactory;

  private FastStack _active_undoable_once;

  transient private PrintStream _out = System.out;

  /**
   * Constructs a new constrainer - the object that serves as a placeholder
   * for all other constrained objects, constraints, and goals. Each problem
   * should define at least one Constrainer object. All other objects relate
   * to this object.
   *
   * @param s
   *            Constrainer's symbolic name
   */
  public Constrainer(String s) {
    // Debug.print("Constrainer "+s);
    _initial_memory = Runtime.getRuntime().totalMemory()
        - Runtime.getRuntime().freeMemory();
    _max_occupied_memory = _initial_memory;
    _name = new String(s);

    _active_undoable_once = new FastStack();

    _intvars = new FastVector();
    _floatvars = new FastVector();
    _intsetvars = new FastVector();
    _constraints = new FastVector();
    // _goals = new FastVector();

    // _execution_stack = new FastStack();
    // _alternative_stack = new FastStack();
    // _reversibility_stack = new FastStack();

    _reversibility_stack = new UndoStack();
    _goal_stack = new GoalStack(_reversibility_stack);

    _propagation_queue = new FastQueue();

    // _goal_CP_marker = new GoalDisplay(this, "ChoicePointMarker");
    // _undo_CP_marker = new UndoImpl();

    // _save_goal = new GoalDisplay(this,"Save");
    // _restore_goal = new GoalAnd(new GoalDisplay(this, "\nRestore!"),
    // new GoalFail(this));

    _show_internal_names = false;
    _show_variable_names = true;
    _choice_point = 0;
    _number_of_choice_points = 0;
    _number_of_failures = 0;
    _number_of_notifications = 0;
    _failure_display_frequency = 0;
    _number_of_undos = 0;
    _choice_point_objects = new FastVector();
    _failure_objects = new FastVector();
    _backtrack_objects = new FastVector();
    _trace_goals = false;
    _time_limit = 0;
    _time_limit_exceeded = false;

    // _failure = new Failure();
    _trace_failure_stack = false;

    _print_information = false;

    // _undo_subject_factory = new UndoSubjectFactory();

    _expressionFactory = new ExpressionFactoryImpl(this);

  }

  /*
   * ==============================================================================
   * High-level Components
   * ============================================================================
   */
  /**
   * Returns the expression factory for this constrainer.
   */
  public ExpressionFactory expressionFactory() {
    return _expressionFactory;
  }

  /*
   * ReusableFactory undoSubjectFactory() { return _undo_subject_factory; }
   */

  /*
   * ==============================================================================
   * EOF High-level Components
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Constraints
   * ============================================================================
   */
  /**
   * Adds a constraint to the Constrainer. Note: the constraint added by this
   * function should be posted afterwards by {@link #postConstraints()}
   *
   * @param ct
   *            The constraint to be added to the constrainer.
   *
   * @return The constraint passed as the parameter {@link Constraint}.
   */
  public Constraint addConstraint(Constraint ct) {
    _constraints.addElement(ct);
    addUndo(UndoFastVectorAdd.getUndo(_constraints));
    return ct;
  }

  /**
   * Adds a constraint to the Constrainer.
   *
   * Constraint is given in the form of boolean expression. Note: the
   * constraint added by this function should be posted afterwards by
   * {@link #postConstraints()}
   *
   * @param ctExp
   *            The IntBoolExp to be added to the constrainer as a constraint.
   *
   * @return The constraint made from the parameter {@link Constraint}.
   */
  public Constraint addConstraint(IntBoolExp ctExp) {
    return addConstraint(ctExp.asConstraint());
  }

  /**
   * Returns a vector with all currently available constraints.
   *
   * @return Vector of added constraints.
   */
  public FastVector constraints() {
    return _constraints;
  }

  /**
   * Activates the passed constraint. This method executes the specified
   * constraint.The constraint is not added to internal constraint storage
   * (with which {@link #addConstraint(Constraint)} and
   * {@link #postConstraints()} operates) instead it is just activated
   * immediately.
   *
   * @param ct
   *            The constraint to be posted/executed.
   * @throws Failure
   *             When the constraint can not be posted that is the constraint
   *             is incompatible with the previously activated ones.
   */
  public void postConstraint(Constraint ct) throws Failure {
    boolean ok = execute(ct);

    if (!ok) {
      String s = "Posting of constraint failed: " + ct;
      throw new Failure(s);
    }

    // return ok;
  }

  /**
   * Activates the passed constraint. This method executes the specified
   * constraint provided in the form of boolean expression. The constraint is
   * not added to internal constraint storage (with which
   * {@link #addConstraint(Constraint)} and {@link #postConstraints()}
   * operates) instead it is just activated immediately.
   *
   * @param ct
   *            The constraint to post/execute.
   * @throws Failure
   *             When the constraint cannot be posted that is the constraint
   *             is incompatible with the previously activated ones.
   */
  public void postConstraint(IntBoolExp ct) throws Failure {
    postConstraint(ct.asConstraint());
  }

  /**
   * Activates all the added with {@link #addConstraint(Constraint)} and not
   * activated constraints.
   *
   * @throws Failure
   *             When the constraints added with
   *             {@link #addConstraint(Constraint)} are incompatible with the
   *             previously activated ones or together so they can not be
   *             posted.
   */
  public void postConstraints() throws Failure {
    postConstraints(_constraints.toArray());
  }

  /**
   * Posts the set of constraints (or/and IntBoolExp) represented as an array
   * of java.lang.Object. All constraints are being executed immediately.
   *
   * @param constraints
   *            An array of Constraints to post/execute.
   * @throws Failure
   *             When some constraint cannot be posted (constraint is
   *             incompatible with others)
   */
  void postConstraints(Object[] constraints) throws Failure {
    Goal g = GoalPostConstraints(constraints);

    if (g == null)
      return;

    boolean ok = execute(g);

    if (!ok) {
      String s;
      if (constraints.length == 1)
        s = "Posting of constraint failed: " + constraints[0];
      else
        s = "Posting of " + constraints.length + " constraints failed";

      throw new Failure(s);
    }

    // return ok;
  }

  /**
   * @return A goal that executes a set of constraints. Or null if there are
   *         no constraints to post.
   *
   * @param constraints
   *            An array of Constraints.
   */
  Goal GoalPostConstraints(Object[] constraints) {
    Goal g = null;
    for (int i = 0; i < constraints.length; i++) {
      Object o = constraints[i];
      Constraint ct;
      if (o instanceof Constraint) {
        ct = (Constraint) o;
      } else if (o instanceof IntBoolExp) {
        ct = ((IntBoolExp) o).asConstraint();
      } else {
        throw new RuntimeException("Not a constraint: " + o);
      }

      if (ct == null)
        continue;

      if (i == 0)
        g = ct;
      else
        g = new GoalAnd(g, ct);
    }

    return g;
  }

  /*
   * ==============================================================================
   * EOF Constraints
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Goals
   * ============================================================================
   */

  // /**
  // * Adds a goal to the Constrainer.
  // *
  // * @param goal {@link Goal} to be added to the constrainer.
  // */
  // public void addGoal(Goal goal)
  // {
  // _goals.addElement(goal);
  // addUndo( UndoFastVectorAdd.getUndo(_goals) );
  // }
  //
  // /**
  // * @return All added goals.
  // */
  // public FastVector goals()
  // {
  // return _goals;
  // }
  /*
   * ==============================================================================
   * EOF Goals
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Variables
   * ============================================================================
   */
  /**
   * Adds a constrained set variable to the Constrainer
   *
   * @param var
   *            IntSetVar to be added
   * @return passed variable
   */
  IntSetVar addIntSetVar(IntSetVar var) {
    _intsetvars.addElement(var);
    addUndo(UndoFastVectorAdd.getUndo(_intsetvars));
    return var;
  }

  /**
   * Adds an internal constrained set variable to the constrainer
   *
   * @param var
   *            Variable to be added
   * @return passed variable
   */
  IntSetVar addIntSetVarInternal(IntSetVar var) {
    _intsetvars.addElement(var);
    addUndo(UndoFastVectorAdd.getUndo(_intsetvars));
    return var;
  }

  /**
   * Create new constrained set variable and adds it to the constrainer
   *
   * @param values
   *            set of possible values
   * @param name
   *            Symbolic name of the new variable
   * @return variable created based on set of possible values
   */
  public IntSetVar addIntSetVar(int[] values, String name) {
    IntSetVar var = new IntSetVarImpl(this, values, name);
    return addIntSetVar(var);
  }

  /**
   * Create new constrained set variable and adds it to the constrainer
   *
   * @param values
   *            set of possible values
   * @return variable created based on set of possible values
   */
  public IntSetVar addIntSetVar(int[] values) {
    IntSetVar var = new IntSetVarImpl(this, values, "");
    return addIntSetVar(var);
  }

  /**
   * Adds a constrained integer variable to the Constrainer.
   *
   * @param var
   *            Variable to add.
   * @return Passed variable.
   */
  IntVar addIntVar(IntVar var) {
    _intvars.addElement(var);
    addUndo(UndoFastVectorAdd.getUndo(_intvars));
    // addObjectToSymbolicContext(var.name(),var);
    return var;
  }

  /**
   * Adds an internal constrained integer variable to the Constrainer.
   */
  IntVar addIntVarInternal(IntVar var) {
    _intvars.addElement(var);
    addUndo(UndoFastVectorAdd.getUndo(_intvars));
    // addInternalObjectToSymbolicContext(var);
    return var;
  }

  /**
   * Adds an internal constrained integer variable to the Constrainer,
   * selectively allows trace. Used in expressions that create internal
   * variables for their own needs. <br>
   * <b>Note:</b>Constrainer's users should not use this method.
   */
  public IntVar addIntVarTraceInternal(int min, int max, String name,
      int type, int trace) {
    IntVar var = trace != 0 ? new IntVarImplTrace(this, min, max, name,
        type, trace) : new IntVarImpl(this, min, max, name, type);
    return addIntVarInternal(var);
  }

  /**
   * Adds a constrained integer variable to the Constrainer, allows trace.
   */
  public IntVar addIntVarTrace(int min, int max, String name, int type,
      int trace) {
    IntVar var = trace != 0 ? new IntVarImplTrace(this, min, max, name,
        type, trace) : new IntVarImpl(this, min, max, name, type);
    return addIntVar(var);
  }

  /**
   * Adds a constrained integer variable to the Constrainer.
   *
   * @param min
   *            The minimum possible value of the variable being added.
   * @param max
   *            The maximum possible value of the variable being added.
   * @param name
   *            Variable's symbolic name.
   * @param type
   *            The {@link Domain} type of the variable being added.
   * @return The added variable.
   */
  public IntVar addIntVar(int min, int max, String name, int type) {
    IntVar var = new IntVarImpl(this, min, max, name, type);
    return addIntVar(var);
  }

  /**
   * Adds a constrained integer variable to the Constrainer.
   *
   * @param min
   *            The minimum possible value of the variable being added.
   * @param max
   *            The maximum possible value of the variable being added.
   * @param name
   *            Variable's symbolic name.
   * @return The added variable.
   */
  public IntVar addIntVar(int min, int max, String name) {
    return addIntVar(min, max, name, IntVar.DOMAIN_DEFAULT);
  }

  /**
   * Adds a constrained integer variable to the Constrainer.
   *
   * @param min
   *            The minimum possible value of the variable being added.
   * @param max
   *            The maximum possible value of the variable being added.
   * @param type
   *            The {@link Domain} type of the variable being added.
   *
   * @return The added variable.
   */
  public IntVar addIntVar(int min, int max, int type) {
    return addIntVar(min, max, "", type);
  }

  /**
   * Adds a constrained integer variable to the Constrainer.
   *
   * @param min
   *            The minimum possible value of the variable being added.
   * @param max
   *            The maximum possible value of the variable being added.
   * @return The added variable.
   */
  public IntVar addIntVar(int min, int max) {
    return addIntVar(min, max, "", IntVar.DOMAIN_DEFAULT);
  }

  /**
   * Creates an constrained integer variable from the constrained integer
   * expression and posts the "equals" constraint on them.
   *
   * @param exp
   *            The expression to be associated with the new variable.
   * @return The added variable.
   */
  public IntVar addIntVar(IntExp exp) {
    // IntVar var = addIntVar(exp.min(),exp.max(),exp.name());
    IntVar var = addIntVar(exp.min(), exp.max()); // no name to avoid
                            // duplicate name
    try {
      var.equals(exp).post();
    } catch (Failure f) {
      abort("Impossible failure in addIntVar(IntExp exp)");
    }

    return var;
  }

  /**
   * Adds a constrained boolean variable to the Constrainer.
   *
   * @param var
   *            Variable to add.
   * @return Added variable.
   */
  IntBoolVar addIntBoolVar(IntBoolVar var) {
    _intvars.add(var);
    addUndo(UndoFastVectorAdd.getUndo(_intvars));
    // addObjectToSymbolicContext(var.name(),var);
    return var;
  }

  /**
   * Adds an internal constrained boolean variable to the Constrainer.
   */
  IntBoolVar addIntBoolVarInternal(IntBoolVar var) {
    _intvars.add(var);
    addUndo(UndoFastVectorAdd.getUndo(_intvars));
    // addInternalObjectToSymbolicContext(var);
    return var;
  }

  /**
   * Creates and adds a constrained boolean variable to the Constrainer.
   *
   * @param name
   *            Variable's symbolic name.
   *
   * @return The added variable.
   */
  public IntBoolVar addIntBoolVar(String name) {
    IntBoolVar var = new IntBoolVarImpl(this, name);
    return addIntBoolVar(var);
  }

  /**
   * Adds an internal constrained boolean variable to the Constrainer. Used in
   * expressions that create internal variables for their own needs. <br>
   * <b>Note:</b>Constrainer's users should not use this method.
   */
  public IntBoolVar addIntBoolVarInternal(String name) {
    IntBoolVar var = new IntBoolVarImpl(this, name);
    return addIntBoolVarInternal(var);
  }

  /**
   * Creates and adds a constrained boolean variable to the Constrainer.
   *
   * @return The added variable.
   */
  public IntBoolVar addIntBoolVar() {
    return addIntBoolVar("");
  }

  /**
   * Adds a constrained floating-point variable to the Constrainer.
   *
   * @param var
   *            Variable to add.
   * @return Added variable.
   */
  FloatVar addFloatVar(FloatVar var) {
    _floatvars.addElement(var);
    addUndo(UndoFastVectorAdd.getUndo(_floatvars));
    // addObjectToSymbolicContext(var.name(),var);
    return var;
  }

  /**
   * Adds an internal constrained floating-point variable to the Constrainer.
   */
  FloatVar addFloatVarInternal(FloatVar var) {
    _floatvars.addElement(var);
    addUndo(UndoFastVectorAdd.getUndo(_floatvars));
    // addInternalObjectToSymbolicContext(var);
    return var;
  }

  /**
   * Adds a constrained floating-point variable to the Constrainer, allows
   * trace.
   */
  public FloatVar addFloatVarTrace(double min, double max, String name,
      int trace) {
    FloatVar var = trace != 0 ? new FloatVarImplTrace(this, min, max, name,
        trace) : new FloatVarImpl(this, min, max, name);
    return addFloatVar(var);
  }

  /**
   * Adds an internal constrained float variable to the Constrainer,
   * selectively allows trace. Used in expressions that create internal
   * variables for their own needs. <br>
   * <b>Note:</b>Constrainer's users should not use this method.
   */
  public FloatVar addFloatVarTraceInternal(double min, double max,
      String name, int trace) {
    FloatVar var = trace != 0 ? new FloatVarImplTrace(this, min, max, name,
        trace) : new FloatVarImpl(this, min, max, name);
    return addFloatVarInternal(var);
  }

  /**
   * Adds a constrained floating-point variable to the Constrainer.
   *
   * @param min
   *            The minimum possible value of the variable being added.
   * @param max
   *            The maximum possible value of the variable being added.
   * @param name
   *            Variable's symbolic name.
   * @return The added variable.
   */
  public FloatVar addFloatVar(double min, double max, String name) {
    FloatVar var = new FloatVarImpl(this, min, max, name);
    return addFloatVar(var);
  }

  /**
   * Adds a constrained floating-point variable to the Constrainer.
   *
   * @param min
   *            The minimum possible value of variable being added.
   * @param max
   *            The maximum possible value of variable being added.
   * @return The added variable.
   */
  public FloatVar addFloatVar(double min, double max) throws Failure {
    return addFloatVar(min, max, "");
  }

  /**
   * This method returns all integer constrained variables were ever being
   * added. The set of added variables is reversible.
   *
   * @return All integer constrained variables.
   */
  public FastVector integers() {
    return _intvars;
  }

  /**
   * Returns all float constrained variables. The set of added variables is
   * reversible.
   *
   * @return All float constrained variables.
   */
  public FastVector floats() {
    return _floatvars;
  }

  /*
   * ==============================================================================
   * EOF Variables
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Undoable values
   * ============================================================================
   */
  /**
   * Adds an undoable integer to the Constrainer.
   *
   * @param value
   *            Initial value.
   * @param name
   *            Symbolic name.
   * @return Added undoable integer.
   */
  public UndoableInt addUndoableInt(int value, String name) {
    return new UndoableIntImpl(this, value, name);
  }

  /**
   * Adds an undoable integer to the Constrainer.
   *
   * @param value
   *            Initial value.
   * @return Added undoable integer.
   */
  public UndoableInt addUndoableInt(int value) {
    return new UndoableIntImpl(this, value);
  }

  /**
   * Adds an undoable float to the Constrainer.
   *
   * @param value
   *            Initial value.
   * @param name
   *            Symbolic name.
   * @return Added undoable float.
   */
  public UndoableFloat addUndoableFloat(double value, String name) {
    return new UndoableFloatImpl(this, value, name);
  }

  /**
   * Adds an undoable float to the Constrainer.
   *
   * @param value
   *            Initial value.
   * @return Added undoable float.
   */
  public UndoableFloat addUndoableFloat(double value) {
    return new UndoableFloatImpl(this, value);
  }

  /*
   * ==============================================================================
   * EOF Undoable values
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Undo objects
   * ============================================================================
   */
  /**
   * Adds an undo-object to the reversibility stack.
   *
   * @param undo_object
   *            Undo object to add.
   */
  public void addUndo(Undo undo_object) {
    _number_of_undos++;
    // Debug.on();Debug.print("add " + undo_object);Debug.off();
    _reversibility_stack.pushUndo(undo_object);
  }

  /**
   * Adds an undo-object to the reversibility stack for a given undoable
   * object. Some undo-objects can be generated one time between choice
   * points. Constrainer notifies such objects when backtrack or choice point
   * occures.
   *
   * @param undo_object
   *            Undo object to add.
   * @param undoable
   *            Undoable object to add for notification.
   */
  public void addUndo(Undo undo_object, Undoable undoable) {
    addUndo(undo_object);
    // Adds an undoableOnce to the _active_undoable_once.
    // Used in UndoableOnceImpl and allowUndos().
    if (undoable instanceof UndoableOnceImpl)
      _active_undoable_once.push(undoable);
  }

  /**
   * Adds an undoable action. Undoable action is executed during backtracking.
   * It has not change constrainer state (modify variables, add constraints,
   * etc.). It can be used to animate search process. For example, you draw a
   * square during the search and erase it in undoable action during
   * backtracking.
   *
   * @param goal
   *            Undoable goal to add.
   */
  public void addUndoableAction(Goal goal) {
    addUndo(UndoableAction.getUndo(goal));
    allowUndos(); // the action should have the state at the time when it
            // was added
  }

  /**
   * Clears the undone-flags for active undoable once objects. This force them
   * to create undos again. Used: - when a choice point is set - when
   * backtracking is performed
   */
  void allowUndos() {
    while (!_active_undoable_once.empty()) {
      ((UndoableOnceImpl) _active_undoable_once.pop()).restore();
    }
  }

  /*
   * ==============================================================================
   * EOF Undo objects
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Limits
   * ============================================================================
   */
  /**
   * ========== Changed: limit in seconds changed to milliseconds
   *
   * Sets the time limit for the search execution (in milliseconds). 0 means
   * no time limit (default).
   *
   * @param milliseconds
   *            The time limit to be set.
   */
  public void setTimeLimit(long milliseconds) {
    _time_limit = milliseconds;
  }
 
  /**
   * ========== Added: an accessor for limit in seconds
   */
  public long getTimeLimit() {
    return _time_limit;
  }
 
 

  public boolean isTimeLimitExceeded() {
    return _time_limit_exceeded;
  }

  public void setTimeLimitExceeded(boolean _time_limit_exceeded) {
    this._time_limit_exceeded = _time_limit_exceeded;
  }

  /**
   * Sets the limit for the number of failures during a goal execution. 0
   * means no failures limits (default).
   *
   * @param nf
   *            The number of failures to be set as the limit.
   */
  public void setFailuresLimit(long nf) {
    _failures_limit = nf;
  }

  /*
   * ==============================================================================
   * EOF Limits
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Statistics, metrics, flags, ...
   * ============================================================================
   */
  /**
   * This method return number of failures during search execution.
   *
   * @return Number of failures during execution.
   */
  public int numberOfFailures() {
    return _number_of_failures;
  }

  /**
   * Sets the number of choice points. Used internally in some goals. <br>
   * <b>Note:</b>Constrainer's users should not use this method.
   *
   * @param nfs
   *            Number of failures.
   */
  public void numberOfFailures(int nfs) {
    _number_of_failures = nfs;
  }

  /**
   * This method returns the number of choice points during search execution.
   *
   * @return The number of choice points during execution.
   */
  public int numberOfChoicePoints() {
    return _number_of_choice_points;
  }

  /**
   * Sets the number of choice points. Used internally in some goals. <br>
   * <b>Note:</b>Constrainer's users should not use this method.
   *
   * @param cps
   *            Number of choice points.
   */
  public void numberOfChoicePoints(int cps) {
    _number_of_choice_points = cps;
  }

  /**
   * Return the search execution time.
   *
   * @return The search execution time in milliseconds.
   */
  public long executionTime() {
    return _execution_time;
  }

  /**
   * Used internally in the implementation of subject when it sends a
   * notificaction event. <br>
   * <b>Note:</b>Constrainer's users should not use this method.
   */
  public void incrementNumberOfNotifications() {
    _number_of_notifications++;
  }

  /**
   * This method returns the number of notifications occured during search
   * execution.
   *
   * @return The number of notifications.
   */
  public long numberOfNotifications() {
    return _number_of_notifications;
  }

  /**
   * Controls whether to show the internal names for the expressions.
   *
   * @param flag
   *            true if show.
   */
  public void showInternalNames(boolean flag) {
    _show_internal_names = flag;
  }

  /**
   * Returns true if internal names for the expressions are shown.
   *
   * @return true if internal names for the expressions are shown.
   */
  public boolean showInternalNames() {
    return _show_internal_names;
  }

  /**
   * Changes variable names printing behaviour.
   *
   * @param flag
   *            Boolean parameter. To enable printing should be set to true
   *            and otherwise to false.
   */
  public void showVariableNames(boolean flag) {
    _show_variable_names = flag;
  }

  /**
   * Returns variable names printing behaviour flag.
   *
   * @return the variable names printing flag.
   */
  public boolean showVariableNames() {
    return _show_variable_names;
  }

  /**
   * Enables printing the internal constrainer's information.
   */
  public void printInformation() {
    _print_information = true;
  }

  /**
   * Sets the precision of the constrained floating-point variable
   * calculations� The default value is 1E-06.
   *
   * @param prc
   *            The new precision to be set.
   */
  static public void precision(double prc) {
    FLOAT_PRECISION = prc;
  }

  /**
   * Returns the precision of the constrained floating-point variable
   * calculations.
   *
   * @return the precision of the constrained floating-point variable
   *         calculations.
   */
  static public double precision() {
    return FLOAT_PRECISION;
  }

  /*
   * ==============================================================================
   * EOF Statistics, metrics, flags, ...
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Tracing
   * ============================================================================
   */

  /**
   * The function turns on the tracing for the subject. The expression is
   * printed to {@link #out()} every time when subject send notification
   * event.<br>
   * For example, when domain of the consstraint expression changed.
   *
   * @param subject
   *            the expression to be watched for modifications.
   */
  public void trace(Subject subject) {
    subject.trace();
  }

  /**
   * The function turns on the tracing for the array of the constrained
   * integer expressions. The array is printed to {@link #out()} every time
   * when at least one variable from this vector is modified.
   *
   * @param vars
   *            the array to be watched for modifications.
   */
  public void trace(IntExpArray vars) {
    class ObserverTraceVars extends Observer {
      private IntExpArray _vars;

      ObserverTraceVars(IntExpArray vars) {
        _vars = vars;
      }

      public void update(Subject var, EventOfInterest interest)
          throws Failure {
        _out.println("Trace " + interest + ": " + _vars);
      }

      public int subscriberMask() {
        return EventOfInterest.ALL;
      }

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

    } // ~ ObserverTraceVars

    Observer observer = new ObserverTraceVars(vars);
    for (int i = 0; i < vars.size(); i++) {
      Subject var = (Subject) vars.get(i);
      var.attachObserver(observer);
    }
  }

  /**
   * Performs tracing during backtracking.
   *
   * @param obj
   *            Object that is printed using toString() method.
   */
  public void traceBacktracks(Object obj) {
    _backtrack_objects.addElement(obj);
  }

  /**
   * Turns on the tracing of the failures. Object is printed to {@link #out()}
   * when failure occures.
   *
   * @param frequency
   *            Frequency of the tracing.
   * @param obj
   *            Object to print.
   */
  public void traceFailures(int frequency, Object obj) {
    _failure_display_frequency = frequency;
    if (obj != null)
      _failure_objects.addElement(obj);
  }

  /**
   * Turns on the tracing of the failures.
   *
   * @param frequency
   *            Frequency of the tracing.
   */
  public void traceFailures(int frequency) {
    traceFailures(frequency, null);
  }

  /**
   * Turns on the tracing of every failure.
   */
  public void traceFailures() {
    traceFailures(1);
  }

  /**
   * Tells the constrainer to display the Java stack trace when a failure
   * occurs. To control the frequency of such displaying, use
   * traceFailres(frequency). For example, to display the stack on failure#25,
   * use: C.traceFailureStack(); C.traceFailures(25);
   */
  public void traceFailureStack() {
    _trace_failure_stack = true;
  }

  /**
   * Turns on the tracing of every failure. Object is printed to
   * {@link #out()} when failure occures.
   *
   * @param obj
   *            Object to print.
   */
  public void traceFailures(Object obj) {
    traceFailures(1, obj);
  }

  /**
   * Returns true if failure tracing is on.
   *
   * @return true if failure tracing is on.
   */
  public boolean showFailures() {
    return (_failure_display_frequency > 0);
  }

  /**
   * Turn on tracing of the goal execution.
   */
  public void traceExecution() {
    showInternalNames(true);
    _trace_goals = true;
  }

  /**
   * Turn on tracing of choice points. Object is printed to {@link #out()}
   * when choice point occures.
   *
   * @param obj
   *            Object to print.
   */
  public void traceChoicePoints(Object obj) {
    _choice_point_objects.addElement(obj);
  }

  /**
   * The function turns off all tracings for the Constrainer.
   */
  public void traceOff() {
    showInternalNames(false);
    _trace_goals = false;
    _backtrack_objects.clear();
    _choice_point_objects.clear();
    _failure_objects.clear();
    _trace_failure_stack = false;
    _failure_display_frequency = 0;
  }

  /*
   * ==============================================================================
   * EOF Tracing
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Special expressions, constraints, ...
   * ============================================================================
   */
  /**
   * Returns constrained set being intersection of two sets variables passed
   *
   * @param var1
   *            first constrained set variable
   * @param var2
   *            second constrained set variable
   * @return var1.intersectionWith(var2)
   */
  public IntSetVar intersection(IntSetVar var1, IntSetVar var2) {
    return var1.intersectionWith(var2);
  }

  /**
   * Returns constrained set variable being union of two sets
   *
   * @param var1
   *            first constrained set variable
   * @param var2
   *            second constrained set variable
   * @return var1.unionWith(var2)
   */
  public IntSetVar union(IntSetVar var1, IntSetVar var2) {
    return var1.unionWith(var2);
  }

  /**
   * Returns expression being equal to the number of required values in a set
   * domain
   *
   * @param var
   *            constrained set variable
   * @return var.cardinality() expression
   */
  public IntExp cardinality(IntSetVar var) {
    return var.cardinality();
  }

  /**
   * States that two sets has empty intersection
   *
   * @param var1
   *            first constrained set variable
   * @param var2
   *            second constrained set variable
   * @return var1.nullIntersectionWith(var2) constraint
   */
  public Constraint nullIntersect(IntSetVar var1, IntSetVar var2) {
    return var1.nullIntersectWith(var2);
  }

  /**
   * Returns expression: sum of passed expressions: var1.add(var2)
   *
   * @param var1
   *            First expression
   * @param var2
   *            Second expression
   * @return var1.add(var2) expression
   */
  public IntExp sum(IntExp var1, IntExp var2) {
    return var1.add(var2);
  }

  /**
   * Returns the constrained integer expression that equals to the sum of all
   * expressions from the array.
   *
   * @param vars
   *            The array of constrained integer expressions to sum.
   * @return the constrained integer expression equal to the sum.
   */
  public IntExp sum(IntExpArray vars) {
    /*
     * int min = 0; int max = 0; for(int i=0; i < vars.size(); ++i) { IntVar
     * var = (IntVar)vars.elementAt(i); min += var.min(); max += var.max(); }
     * IntVar result = addIntVar(min,max); execute(new
     * ConstraintAddVector(vars,result)); return result;
     */
    return vars.sum();
  }

  /**
   * Returns the constrained integer expression that equals to the scalar
   * product of the array of constrained integer expressions and the array of
   * <b>int</b> values. The expression has the following symbolic form:
   * exps[0]*values[0] + exps[1]*values[1] + ...
   *
   * @param exps
   *            The array of constrained integer expressions.
   * @param values
   *            The array of <b>int</b> values.
   * @return The scalar product constrained integer expression.
   */
  public IntExp scalarProduct(IntExpArray exps, int[] values) {
    int size = exps.size();

    if (values.length != size)
      throw new RuntimeException(
          "scalarProduct parameters have different size");

    IntExpArray products = new IntExpArray(this, size);
    for (int i = 0; i < size; i++) {
      products.set(exps.elementAt(i).mul(values[i]), i);
    }

    return products.sum();
  }

  /**
   * Returns the constrained floating-point expression that equals to the
   * scalar product of the array of constrained floating-point expressions and
   * the array of <b>double</b> values. The expression has the following
   * symbolic form: exps[0]*values[0] + exps[1]*values[1] + ...
   *
   * @param exps
   *            The array of constrained floating-point expressions.
   * @param values
   *            The array of <b>double</b> values.
   * @return The scalar product constrained floating-point expression.
   */
  public FloatExp scalarProduct(FloatExpArray exps, double[] values) {
    int size = exps.size();

    if (values.length != size)
      throw new RuntimeException(
          "scalarProduct parameters have different size");

    FloatExpArray products = new FloatExpArray(this, size);
    for (int i = 0; i < size; i++) {
      products.set(exps.elementAt(i).mul(values[i]), i);
    }

    return products.sum();
  }

  /**
   * Returns the constrained floating-point expression that equals to the
   * scalar product of the array of constrained integer expressions and the
   * array of <b>double</b> values. The expression has the following symbolic
   * form: exps[0]*values[0] + exps[1]*values[1] + ...
   *
   * @param exps
   *            The array of constrained integer expressions.
   * @param values
   *            The array of <b>double</b> values.
   * @return The scalar product constrained floating-point expression.
   */
  public FloatExp scalarProduct(IntExpArray exps, double[] values) {
    int size = exps.size();

    if (values.length != size)
      throw new RuntimeException(
          "scalarProduct parameters have different size");

    FloatExpArray products = new FloatExpArray(this, size);
    for (int i = 0; i < size; i++) {
      products.set(exps.elementAt(i).mul(values[i]), i);
    }

    return products.sum();
  }

  /**
   * Returns a constrained integer expression that is equal to the number of
   * variables in "vars" bound to the "value".
   *
   * @param intvars
   *            The array of constrained integer expressions.
   * @param value
   *            The value to be checked.
   * @return The constrained integer expression that is equal to the number of
   *         variables in "vars" bound to the "value".
   * @throws Failure
   */
  public IntExp cardinality(IntExpArray intvars, int value) throws Failure {
    // IntVar card = addIntVar(0,intvars.size(),"Count of "+value);
    // ConstraintCardinality ct = new
    // ConstraintCardinality(intvars,value,card);
    // ct.execute(); // may fail
    // return card;

    return intvars.cards().cardAt(value);

  }

  /**
   * All elements of an array are associated with their domains. The union of
   * the domains makes up the array "domain" that is the set of all values
   * that may occur in the array. An instance of {@link IntArrayCards} class
   * is associated with each instance of {@link IntExpArray}. The instance
   * keeps track the possible number of the value occurrences in the array
   * that is it has an element(constrained integer expression) per value from
   * the array "domain". For each value from the array "domain" the method
   * {@link #distribute(IntExpArray , IntExpArray)} creates the constraint
   * "equals" to the number of occurrences of values. The number of
   * occurrences for each value of array "domain" is specified in
   * <code>cards</code> parameter.
   *
   * @param vars
   *            The array of constrained integer expressions.
   * @param cards
   *            The array of value occurences.
   * @return The array of value cardinalities.
   * @throws Failure
   */
  public IntArrayCards distribute(IntExpArray vars, IntExpArray cards)
      throws Failure {
    IntArrayCards vcards = vars.cards();

    for (int i = 0; i < vcards.cardSize(); ++i) {
      Constraint ct = vcards.cardAt(i).equals(cards.get(i));
      ct.execute();
    }

    return vcards;

  }

  /**
   * Returns an array of constrained integer variables "cards" such that
   * cards[i] is equal to the number of variables in "vars" bound to the value
   * values[i].
   */

  /*
   * public Vector distribute(Vector vars, int[] values) throws Failure {
   * Vector cards = new Vector(); for(int i=0; i< values.length; ++i) {
   * cards.addElement(cardinality(vars,values[i]));
   * //cards.addElement(addIntVar(0,vars.size(),"Count of "+values[i])); } //
   * redundant constraint IntExp card_sum = new IntExpAddVector(this, cards);
   * card_sum.less(vars.size()+1).execute(); return cards; }
   */

  /**
   * Returns the array of constrained integer variables "cards" such that
   * cards[i] is equal to the number of variables in "vars" bound to the value
   * values[i].
   *
   * @param vars
   *            The array of constrained ineteger variables.
   * @param values
   *            The array of value to be checked.
   *
   * @return The array of values cardinalities in vars.
   * @throws Failure
   */
  public IntExpArray distribute(IntExpArray vars, int[] values)
      throws Failure {

    IntArrayCards vcards = vars.cards();

    FastVector cards = new FastVector();

    for (int i = 0; i < values.length; ++i) {
      cards.addElement(vcards.cardAt(values[i]));
      // cards.addElement(addIntVar(0,vars.size(),"Count of "+values[i]));
    }
    // redundant constraint
    return new IntExpArray(this, cards);
  }

  /**
   * Returns an array of constrained integer variables "cards" such that
   * cards[i] is equal to the number of variables in "vars" bound to the
   * sequental [0,vars.size()] values.
   *
   * @param vars
   *            Array of variables.
   * @return An array of constrained integer variables.
   * @throws Failure
   */
  public IntExpArray distribute(IntExpArray vars) throws Failure {
    int size = vars.size();
    int[] values = new int[size];
    for (int i = 0; i < size; ++i) {
      values[i] = i;
    }

    return distribute(vars, values);

  }

  /**
   * Returns an array of n constrained integer variables "cards" such that
   * cards[i] is equal to the number of variables in "vars" bound to the value
   * i.
   *
   * @param vars
   *            The array of constrained ineteger expressions.
   * @param n
   *            The value to be checked.
   * @return The array of value cardinalities.
   * @throws Failure
   */
  public IntExpArray distribute(IntExpArray vars, int n) throws Failure {
    int[] values = new int[n];
    for (int i = 0; i < n; ++i) {
      values[i] = i;
    }
    return distribute(vars, values);
  }

  /**
   * Creates "All Different" constraint.
   *
   * @param intvars
   *            The array of constrained integer variables.
   * @return Constraint stating that all variables in the specified array must
   *         be different.
   */
  public Constraint allDiff(IntExpArray intvars) {
    return new ConstraintAllDiff(intvars);
  }

  /*
   * ==============================================================================
   * EOF Special expressions, constraints, ...
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Execution, backtracking, choice points
   * ============================================================================
   */
  /**
   * Backtracks to the most recent choice point.
   */
  boolean backtrack() {
    return backtrack(null);
  }

  /**
   * Backtracks to the most recent labeled choice point.
   */
  boolean backtrack(ChoicePointLabel label) {
    boolean success = _goal_stack.backtrack(label);

    allowUndos();

    if (success) {
      if (_backtrack_objects.size() > 0)
        printObjects(_out, "BACKTRACK: ", _backtrack_objects);
    }

    return success;
  }

  /**
   * Executes the goal without state restoration.
   *
   * @return true if success
   * @param goal
   *            com.exigen.ie.constrainer.Goal
   */
  public boolean execute(Goal goal) {
    return execute(goal, false);
  }

  /**
   * Executes the search goal provided by the first parameter. In most cases,
   * the goal is expected to find a solution: to instantiate all constrained
   * objects and satisfied all constraints. Return true if the solution is
   * found. Returns false otherwise. The second parameter allows a user to
   * restore the state of the constrainer after the succesful execution of the
   * main_goal.
   *
   * @return true if success
   * @param main_goal
   *            com.exigen.ie.constrainer.Goal
   * @param restore_flag
   *            boolean
   */
  synchronized public boolean execute(Goal main_goal, boolean restore_flag) {
    long execution_start = System.currentTimeMillis();
    //setTimeLimitExceeded(false);

    boolean success = true;

    // long start_seconds = System.currentTimeMillis()/1000; == changed by
    // OR to milliseconds
    long start_milliseconds = System.currentTimeMillis();

    // save current _goal_stack
    GoalStack old_goal_stack = _goal_stack;

    _goal_stack = new GoalStack(main_goal, _reversibility_stack);

    allowUndos();

    while (!_goal_stack.empty()) {
      try {
        Goal goal = _goal_stack.popGoal();

        if (_trace_goals) {
          _out.println("Execute: " + goal);
        }

        goal = goal.execute();
        propagate();

        if (_print_information) {
          long occupied_memory = Runtime.getRuntime().totalMemory()
              - Runtime.getRuntime().freeMemory();
          if (_max_occupied_memory < occupied_memory)
            _max_occupied_memory = occupied_memory;
        }

        if (goal != null) {
          _goal_stack.pushGoal(goal);
        }
      } catch (Failure f) {

        if (_trace_failure_stack
            && _failure_display_frequency > 0
            && _number_of_failures % _failure_display_frequency == 0) {
          f.printStackTrace(_out);
        }

        if (_print_information) {
          long occupied_memory = Runtime.getRuntime().totalMemory()
              - Runtime.getRuntime().freeMemory();
          if (_max_occupied_memory < occupied_memory)
            _max_occupied_memory = occupied_memory;
        }

        clearPropagationQueue();

        // here was checking out the time limit
        // check time limit
        if (_time_limit > 0) {
          // long now_seconds = System.currentTimeMillis()/1000; ====
          // ===== Changed by OR
          long now_milliseconds = System.currentTimeMillis();
          if (now_milliseconds - start_milliseconds > _time_limit) {
            String msg = "Time limit for one solution search " + _time_limit + " mills has been exceeded";
            setTimeLimitExceeded(true);
            _out.println(msg);
            success = false;
            throw new TimeLimitException(msg, f.label());
            //break;
          }
        }

        // check failures limit
        if (_failures_limit > 0) {
          if (_number_of_failures > _failures_limit) {
            _out.println("Failures Limit Violation: more than "
                + _failures_limit);
            success = false;
            break;
          }
        }

        // Backtrack
        if (!backtrack(f.label())) {
          success = false;
          break;
        }
      } catch (Throwable t) {
        _out.println("Unexpected exception: " + t.toString());
        t.printStackTrace(_out);
        abort("Unexpected exception: ", t);
      }

    } // ~while

    boolean restoreAnyway = restore_flag || !success;
    if (restoreAnyway) {
      _reversibility_stack.backtrack(_goal_stack.undoStackSize());
    }

    _execution_time += System.currentTimeMillis() - execution_start;

    if (_print_information) {
      if (!(main_goal instanceof Constraint))
        doPrintInformation();
    }

    _goal_stack = old_goal_stack;

    return success;
  }

  /**
   * @param label
   * @param restore_flag
   */
  synchronized public boolean toContinue(ChoicePointLabel label,
      boolean restore_flag) {
    long execution_start = System.currentTimeMillis();

    boolean success = true;

    // long start_seconds = System.currentTimeMillis()/1000; === Changed by
    // OR to milliseconds
    long start_milliseconds = System.currentTimeMillis();
    // save current _goal_stack
    GoalStack old_goal_stack = _goal_stack;

    // _goal_stack = new GoalStack(main_goal, _reversibility_stack);

    allowUndos();
    // Backtrack
    if (!backtrack(label)) {
      success = false;
    }

    if (success)
      while (!_goal_stack.empty()) {
        try {
          Goal goal = _goal_stack.popGoal();

          if (_trace_goals) {
            _out.println("Execute: " + goal);
          }

          goal = goal.execute();
          propagate();

          if (_print_information) {
            long occupied_memory = Runtime.getRuntime()
                .totalMemory()
                - Runtime.getRuntime().freeMemory();
            if (_max_occupied_memory < occupied_memory)
              _max_occupied_memory = occupied_memory;
          }

          if (goal != null) {
            _goal_stack.pushGoal(goal);
          }
        } catch (Failure f) {

          if (_trace_failure_stack
              && _failure_display_frequency > 0
              && _number_of_failures % _failure_display_frequency == 0) {
            f.printStackTrace(_out);
          }

          if (_print_information) {
            long occupied_memory = Runtime.getRuntime()
                .totalMemory()
                - Runtime.getRuntime().freeMemory();
            if (_max_occupied_memory < occupied_memory)
              _max_occupied_memory = occupied_memory;
          }

          clearPropagationQueue();

          // check time limit
          if (_time_limit > 0) {
            // long now_seconds = System.currentTimeMillis()/1000;
            // ====Changed by OR to milliseconds
            long now_milliseconds = System.currentTimeMillis();
            if (now_milliseconds - start_milliseconds > _time_limit) {
              String msg = "Time limit for one solution search " + _time_limit + " mills has been exceeded";
               _out.println(msg);
               setTimeLimitExceeded(true);
               success = false;
               throw new TimeLimitException(msg,f.label());
               //break;
            }
          }

          // check failures limit
          if (_failures_limit > 0) {
            if (_number_of_failures > _failures_limit) {
              _out.println("Failures Limit Violation: more than "
                  + _failures_limit);
              success = false;
              break;
            }
          }

          // Backtrack
          if (!backtrack(f.label())) {
            success = false;
            break;
          }
        } catch (Throwable t) {
          _out.println("Unexpected exception: " + t.toString());
          t.printStackTrace(_out);
          abort("Unexpected exception: ", t);
        }

      } // ~while

    boolean restoreAnyway = restore_flag || !success;
    if (restoreAnyway) {
      _reversibility_stack.backtrack(_goal_stack.undoStackSize());
    }

    _execution_time += System.currentTimeMillis() - execution_start;
    /*
     * if (_print_information) { if(!(main_goal instanceof Constraint))
     * doPrintInformation(); }
     */
    _goal_stack = old_goal_stack;

    return success;
  }

  /**
   * Sets a choice point between two goals.
   */
  void setChoicePoint(Goal g1, Goal g2) {
    setChoicePoint(g1, g2, null);
  }

  /**
   * Sets a labeled choice point between two goals.
   */
  void setChoicePoint(Goal g1, Goal g2, ChoicePointLabel label) {
    _number_of_choice_points++;

    _goal_stack.setChoicePoint(g1, g2, label);

    allowUndos();

    if (_choice_point_objects.size() > 0)
      printObjects(_out, "CP " + (_choice_point - 1) + ":",
          _choice_point_objects);
  }

  /**
   * Pushes the goal onto the goal stack.
   */
  void pushOnExecutionStack(Goal goal) {
    _goal_stack.pushGoal(goal);
  }

  /**
   * generate a unique ChoicePointLabel
   *
   */
  public ChoicePointLabel createChoicePointLabel() {
    _labelsCounter++;
    return new ChoicePointLabel(this, _labelsCounter);
  }

  /**
   * Returns the label of the current choice point.
   */
  ChoicePointLabel currentChoicePointLabel() {
    return _goal_stack.currentChoicePoint().label();
  }

  /**
   * Returns a number of the last solution (total amount of available
   * solutions) Checks from 0 to max_sol
   *
   * @param max_sol
   *            Maximum solution number to check.
   * @return Nuber of the last solution or max_sol
   */
  public int getSolutionsNumber(Goal main_goal, int max_sol) {
    GoalCheckSolutionNumber check = new GoalCheckSolutionNumber(this,
        max_sol);
    Goal goal = new GoalAnd(main_goal, check);
    if (execute(goal, true))
      return max_sol;
    else
      return check.getCurrentSolutionNumber();
  }

  /**
   * Executes the search goal provided by the first parameter to find a
   * solution with the "solution_number".
   *
   * @param main_goal
   *            Goal to execute
   * @param solution_number
   *            Number of desired solution
   * @param restore_flag
   *            Restoration flag.
   * @return true if success
   */
  public boolean execute(Goal main_goal, int solution_number,
      boolean restore_flag) {
    Goal goal = new GoalAnd(main_goal, new GoalCheckSolutionNumber(this,
        solution_number));
    return execute(goal, restore_flag);
  }

  /**
   * Executes the search goal provided by the first parameter to find a
   * solution with the "solution_number".
   *
   * @param main_goal
   *            Goal to execute.
   * @param solution_number
   *            Solution to find.
   * @return true if success
   */
  public boolean execute(Goal main_goal, int solution_number) {
    return execute(main_goal, solution_number, false);
  }

  /**
   * Executes the search goal provided by the first parameter to find all the
   * problem solutions. Each solution should be saved/printed inside the
   * main_goal. After the goal execution the state of the constrainer is
   * restored.
   *
   * @param main_goal
   *            The goal to execute.
   * @return true if the goal has been successfully executed.
   */
  public boolean executeAll(Goal main_goal) {
    Goal all_solutions = new GoalAllSolutions(main_goal);
    return execute(all_solutions);
  }

  /*
   * ==============================================================================
   * EOF Execution, backtracking, choice points
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Propagation
   * ============================================================================
   */
  /**
   * Adds the subject (usually variable) to the propagation queue. It happenes
   * when the subject changes its state. The notificatioin events will be
   * generated in {@link #propagate} method.
   */
  public void addToPropagationQueue(Subject subject) {
    _propagation_queue.push(subject);
  }

  /**
   * Propagate events triggered by successful goal execution.
   */
  final public void propagate() throws Failure {
    while (!_propagation_queue.empty()) {
      Subject var = (Subject) _propagation_queue.pop();
      var.inProcess(false);
      var.propagate(); // may fail
      // if (!var.inProcess())
      // var.clearPropagationEvents();
    }
  }

  /**
   * Clears the propagation queue.
   */
  void clearPropagationQueue() {
    while (!_propagation_queue.empty()) {
      Subject var = (Subject) _propagation_queue.pop();
      var.inProcess(false);
      // var.clearPropagationEvents();
    }
  }

  /*
   * ==============================================================================
   * EOF Propagation
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Failures
   * ============================================================================
   */
  /**
   * Throws Failure exception.
   *
   * @throws Failure
   */
  public void fail() throws Failure {
    fail("");
  }

  /**
   * Throws Failure exception.
   *
   * @param s
   *            The diagnostic message.
   * @throws Failure
   */
  public void fail(String s) throws Failure {
    fail(s, null);
  }

  /**
   * Throws Failure exception.
   *
   * @param s
   *            The diagnostic message.
   * @throws Failure
   */
  public void fail(String s, ChoicePointLabel label) throws Failure {
    _number_of_failures++;

    if (_failure_display_frequency > 0
        && _number_of_failures % _failure_display_frequency == 0) {
      _out.println("Failure " + _number_of_failures + ": " + s);
    }

    if (_failure_display_frequency == 0
        || _number_of_failures % _failure_display_frequency == 0)
      for (int i = 0; i < _failure_objects.size(); i++) {
        _out.println("Failure: " + s + " "
            + _failure_objects.elementAt(i));
      }

    /*
     * if (showInternalNames()) _failure.message(s); else
     * _failure.message("");
     */
    throw new Failure(s, label);// _failure; //
  }

  /*
   * ==============================================================================
   * EOF Failures
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Misc: toString(), helpers, ...
   * ============================================================================
   */
  /**
   * This method aborts the program execution. It prints the "msg" and the
   * stack trace. Used to display "impossible" errors.
   *
   * @param msg
   *            Diagnostic message to print.
   */
  static public void abort(String msg) {
    abort(msg, new RuntimeException(msg));
  }

  static public void abort(String msg, Throwable t) {
    throw RTExceptionWrapper.wrap(msg, t);
  }

  /**
   * Prints the statistical information. This information is accumulated
   * during the execution of the goals.
   */
  void doPrintInformation() {
    _out.println("\nChoice Points: " + _number_of_choice_points
        + "  Failures: " + _number_of_failures + "  Undos: "
        + _number_of_undos + "  Notifications: "
        + _number_of_notifications + "  Memory: "
        + (_max_occupied_memory - _initial_memory) + "  Time: "
        + _execution_time + "msec");
  }

  /**
   * Helper to print the vector of obects.
   *
   */
  static void printObjects(PrintStream out, String prefix, FastVector objects) {
    int size = objects.size();
    Object[] data = objects.data();
    for (int i = 0; i < size; i++) {
      out.print(prefix);
      out.println(data[i]);
    }
  }

  /**
   * Returns the string representation of the constrainer.
   *
   * @return the string representation of the constrainer.
   */
  public String toString() {
    return "Constrainer: " + _name + "\n" + _goal_stack + "\n"
        + _reversibility_stack;

  }

  /**
   * Returns the Constrainer's output stream where the output information is
   * printed out.
   *
   * @return the Constrainer's output stream where the output information is
   *         printed out.
   */
  public PrintStream out() {
    return _out;
  }

  /**
   * Sets the output stream where the information is printed.
   *
   * @param out
   *            the output stream to be set for Constrainer's output.
   */
  public void out(PrintStream out) {
    _out = out;
  }

  /*
   * ==============================================================================
   * EOF Misc: helpers,...
   * ============================================================================
   */

  /*
   * ==============================================================================
   * Symbolic context and expressions
   * ============================================================================
   */

  // /**
  // * Adds an internal object to the symbolic context.
  // */
  // void addInternalObjectToSymbolicContext(Object o)
  // {
  // try
  // {
  // symbolicContext().addInternalVar(o);
  // }
  // catch(Exception e)
  // {
  // _out.println(e.getMessage());
  // }
  // }
  // /**
  // * Adds named object to the symbolic context.
  // */
  // void addObjectToSymbolicContext(String name, Object o)
  // {
  // try
  // {
  // symbolicContext().setVar(name,o);
  // }
  // catch(Exception e)
  // {
  // _out.println(e.getMessage());
  // }
  // }

  /**
   * Returns context for this constrainer.
   */
  // Context constrainerContext()
  // {
  // Context cxt1 = new ObjectContext(getClass(),this);
  // Context cxt2 = new ConstrainerContext(this);
  // cxt2.setParent(cxt1);
  // return cxt2;
  // }
  /**
   * Evaluate a code written in the symbolic form.
   */
  // Object evaluateSpl(String s) throws Exception
  // {
  // s = s + ";";
  // Context cxt = constrainerContext();
  // Algebra algebra = Algebra.constrainerAlgebra();
  //
  // SplCode code = new SplCode(s);
  // code.validate(cxt,algebra);
  // return code.evaluate(cxt, algebra);
  // }
  /**
   * Evaluate a constraint written in the symbolic form.
   */
  // public Constraint evaluateConstraint(String s) throws Exception
  // {
  // Object result = evaluateSpl(s);
  //
  // if(result instanceof IntBoolExp)
  // {
  // return ((IntBoolExp)result).asConstraint();
  // }
  // else if(result instanceof Constraint)
  // {
  // return (Constraint)result;
  // }
  // else
  // {
  // throw new Exception( "Invalid constraint."
  // + " String: '" + s + "'."
  // + " Result: '" + result + "'." );
  // }
  //
  // }
  /**
   * Adds a constraint written in the symbolic form. Note: the constraint
   * added by this function should be posted afterwards by
   * {@link #postConstraints()}
   *
   * @param s
   *            The string representing constraint.
   *
   * @return The constraint made from the parameter {@link Constraint}.
   */
  // public Constraint addConstraint(String s) throws Exception
  // {
  // Constraint ct = evaluateConstraint(s);
  // addConstraint(ct);
  // return ct;
  // }
  /**
   * Posts a constraint written in the symbolic form. Makes passed constraint
   * active. This method executes specified constraint given in the form of
   * boolean expression. The constraint is not being added to internal
   * constraint storage (with which {@link #addConstraint(Constraint)} and
   * {@link #postConstraints()} operate, but is just being activated
   * immediately.
   *
   * @param s
   *            String represented constraint.
   * @throws Exception
   *             When some constraint cannot be posted (constraint is
   *             incompatible with others) or when string is invalid.
   */
  // void postConstraint(String s) throws Exception
  // {
  // Constraint ct = evaluateConstraint(s);
  // postConstraint(ct);
  // }
  /*
   * ==============================================================================
   * EOF Symbolic expressions
   * ============================================================================
   */
  /*
   * extending to 5.1.0 added by S. Vanskov
   */
  /**
   * Returns a constrained integer expression that is equal to the number of
   * variables in <code> array </code> bound to the value of
   * <code> exp <code>.
   *
   * @param array The array of constrained integer expressions.
   * @param exp The constrained integer expression to be checked.
   *
   * @return The constrained integer expression that is equal to the number
   * of variables in <code> array </code> bound to the value of <code> exp <code>.
   *
   * @throws Failure
   */
  public IntExp cardinality(IntExpArray array, IntExp exp) throws Failure {
    return new IntExpCardIntExp(array, exp);
  }

  /* EO additions */

  /**
   * functions providing the possibility of supporting multi-session added by
   * E. Tseitlin
   */

  IntVar[] getIntVars(int[] indices) {
    if (indices == null)
      return null;
    IntVar[] ari = new IntVar[indices.length];
    Object[] vars = _intvars.data();
    for (int i = 0; i < indices.length; i++) {
      ari[i] = (IntVar) vars[indices[i]];
    }
    return ari;
  }

  FloatVar[] getFloatVars(int[] indices) {
    if (indices == null)
      return null;
    FloatVar[] ari = new FloatVar[indices.length];
    Object[] vars = _floatvars.data();
    for (int i = 0; i < indices.length; i++) {
      ari[i] = (FloatVar) vars[indices[i]];
    }
    return ari;
  }

  int[] findAppropriate(IntVar[] intVars) {
    if (intVars == null)
      return null;
    int size = intVars.length;
    int[] indices = new int[size];
    java.util.HashMap map = new java.util.HashMap(size);
    Object[] vars = _intvars.data();
    for (int i = 0; i < vars.length; i++) {
      map.put(vars[i], new Integer(i));
    }
    int validsCounter = 0;
    for (int i = 0; i < size; i++) {
      Integer idx = (Integer) (map.get(intVars[i]));
      if (idx != null) {
        indices[validsCounter] = idx.intValue();
        validsCounter++;
      }
    }
    int[] out = new int[validsCounter];
    System.arraycopy(indices, 0, out, 0, validsCounter);
    return out;
  }

  int[] findAppropriate(FloatVar[] floatVars) {
    if (floatVars == null)
      return null;
    int size = floatVars.length;
    int[] indices = new int[size];
    java.util.HashMap map = new java.util.HashMap(size);
    Object[] vars = _floatvars.data();
    for (int i = 0; i < vars.length; i++) {
      map.put(vars[i], new Integer(i));
    }
    int validsCounter = 0;
    for (int i = 0; i < size; i++) {
      Integer idx = (Integer) (map.get(floatVars[i]));
      if (idx != null) {
        indices[validsCounter] = idx.intValue();
        validsCounter++;
      }
    }
    int[] out = new int[validsCounter];
    System.arraycopy(indices, 0, out, 0, validsCounter);
    return out;
  }

} // ~Constrainer
TOP

Related Classes of com.exigen.ie.constrainer.ObserverTraceVars

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.