CrossEqual.java

  1. /* Copyright 2015 Laurent COCAULT
  2.  * Licensed to Laurent COCAULT under one or more contributor license agreements.
  3.  * See the NOTICE file distributed with this work for additional information
  4.  * regarding copyright ownership. Laurent COCAULT licenses this file to You
  5.  * under the Apache License, Version 2.0 (the "License"); you may not use this
  6.  * file except in compliance with the License.  You may obtain a copy of the
  7.  * License at
  8.  *
  9.  *   http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.csp.constraint.model.general;

  18. import java.util.ArrayList;
  19. import java.util.Iterator;
  20. import java.util.List;

  21. import org.csp.constraint.model.UnsizedConstraint;
  22. import org.csp.constraint.model.Value;
  23. import org.csp.constraint.model.Variable;

  24. /**
  25.  * Constraint specifying that associate variables from two different lists. When
  26.  * the a variable of one list has the expected value, the variable of the same
  27.  * index of the other list has the other expected value. Example : let's have
  28.  * two array of variables (A, B, C) and (D, E, F). The constraint can specify
  29.  * that when a variable of the first array has a value V1, the corresponding
  30.  * variable of the second array has a value V2. Suppose that during a
  31.  * propagation B take V1 as a value. Then the constraint will value E=V2.
  32.  */
  33. public class CrossEqual<T> extends UnsizedConstraint<T> {

  34.     /** Left array. */
  35.     private List<Variable<T>> left_;

  36.     /** Left value. */
  37.     private Value<T> leftValue_;

  38.     /** Right array. */
  39.     private List<Variable<T>> right_;

  40.     /** Right value. */
  41.     private Value<T> rightValue_;

  42.     /**
  43.      * Constructor.
  44.      * @param leftArray
  45.      *            First array
  46.      * @param leftValue
  47.      *            Expected value for the first array
  48.      * @param rightArray
  49.      *            Second array
  50.      * @param rightValue
  51.      *            Expected value for the second array
  52.      */
  53.     public CrossEqual(final List<Variable<T>> leftArray,
  54.             final Value<T> leftValue, final List<Variable<T>> rightArray,
  55.             final Value<T> rightValue) {
  56.         super("CROSS_EQUAL", new ArrayList<Variable<T>>());
  57.         // Initialize attributes
  58.         left_ = leftArray;
  59.         leftValue_ = leftValue;
  60.         right_ = rightArray;
  61.         rightValue_ = rightValue;
  62.         // Both vector variables are implied in the constraint
  63.         addVariables(leftArray);
  64.         addVariables(rightArray);
  65.     }

  66.     /**
  67.      * {@inheritDoc}
  68.      */
  69.     @Override
  70.     public void propagate() {
  71.         // Propagate in both ways
  72.         propagate(left_, leftValue_, right_, rightValue_);
  73.         propagate(right_, rightValue_, left_, leftValue_);
  74.     }

  75.     /**
  76.      * Propagate constraint in one way : check "from" variables and deduce
  77.      * possible values for "to" variables.
  78.      * @param from
  79.      *            List of variables at the origin of the propagation
  80.      * @param fromValue
  81.      *            Value at the origin of the propagation
  82.      * @param to
  83.      *            List of variables to update
  84.      * @param toValue
  85.      *            Value associated to the fromValue
  86.      */
  87.     protected void propagate(final List<Variable<T>> from,
  88.             final Value<T> fromValue, final List<Variable<T>> to,
  89.             final Value<T> toValue) {

  90.         // Iterate with the index to find the corresponding variable in "to"
  91.         for (int index = 0; index < from.size(); index++) {

  92.             // Get the "from" variable
  93.             final Variable<T> var = from.get(index);

  94.             if (var.isBound() && var.getValue().equals(fromValue)) {

  95.                 // When the "from" variable is bound with the expected value,
  96.                 // the corresponding "to" variable should also be bound.
  97.                 if (to.get(index).setValue(toValue)) {
  98.                     addRecentChangedVariable(to.get(index));
  99.                 }

  100.             } else if (!var.contains(fromValue)) {

  101.                 // When the expected value is no more in the "from" variable
  102.                 // domain, the corresponding "to" value must not be in the
  103.                 // domain of the "to" variable.
  104.                 if (to.get(index).removeValue(toValue)) {
  105.                     addRecentChangedVariable(to.get(index));
  106.                 }

  107.             }
  108.         }
  109.     }

  110.     /**
  111.      * {@inheritDoc}
  112.      */
  113.     @Override
  114.     public String toString() {

  115.         // String builder
  116.         final StringBuilder builder = new StringBuilder();

  117.         // Display the constraint
  118.         builder.append("CROSS_EQUAL(" + leftValue_ + " in (");
  119.         Iterator<Variable<T>> vars = left_.iterator();
  120.         while (vars.hasNext()) {
  121.             // Display every variable
  122.             builder.append(vars.next().getName());
  123.             if (vars.hasNext()) {
  124.                 // Next variable
  125.                 builder.append(", ");
  126.             } else {
  127.                 // Last variable
  128.                 builder.append(") equals " + rightValue_ + " in (");
  129.             }
  130.         }
  131.         vars = right_.iterator();
  132.         while (vars.hasNext()) {
  133.             // Display every variable
  134.             builder.append(vars.next().getName());
  135.             if (vars.hasNext()) {
  136.                 // Next variable
  137.                 builder.append(", ");
  138.             } else {
  139.                 // Last variable
  140.                 builder.append("))");
  141.             }
  142.         }

  143.         return builder.toString();
  144.     }

  145. }