EqualToSum.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.integer;

  18. import org.csp.constraint.model.TernaryConstraint;

  19. /**
  20.  * Constraint specifying that one specific integer variable is the sum of two
  21.  * other integer variables.
  22.  */
  23. public class EqualToSum extends TernaryConstraint<IntValue> {

  24.     /**
  25.      * Constructor of the constraint "FIRST + SECOND = SUM".
  26.      * @param first
  27.      *            First variable
  28.      * @param second
  29.      *            Second variable
  30.      * @param sum
  31.      *            Sum of the two other variables
  32.      */
  33.     public EqualToSum(final IntVar first, final IntVar second, final IntVar sum) {
  34.         super(first.getName() + "+" + second.getName() + "=" + sum.getName(),
  35.                 first, second, sum);
  36.     }

  37.     /**
  38.      * {@inheritDoc}
  39.      */
  40.     @Override
  41.     public void propagate() {

  42.         // The sum minimum is the sum of the other variables minimum and the
  43.         // sum maximum is the sum of the other variables maximum.
  44.         final IntValue sumMin = IntValue.sum(getFirst().getMinValue(),
  45.                 getSecond().getMinValue());
  46.         final boolean sumMinChanged = getSum().reduceWithMinValue(sumMin);
  47.         final IntValue sumMax = IntValue.sum(getFirst().getMaxValue(),
  48.                 getSecond().getMaxValue());
  49.         final boolean sumMaxChanged = getSum().reduceWithMaxValue(sumMax);
  50.         if (sumMaxChanged || sumMinChanged) {
  51.             addRecentChangedVariable(getSum());
  52.         }

  53.         // Propagate the constraint on the first variable
  54.         propagateOnArgument(getFirst(), getSecond(), getSum());

  55.         // Propagate the constraint on the second variable
  56.         propagateOnArgument(getSecond(), getFirst(), getSum());
  57.     }

  58.     /**
  59.      * Propagate the constraint on an argument. The propagation algorithm is the
  60.      * same on the first or the second argument of the constraint: the current
  61.      * method is therefore applied twice with a permutation of the variables.
  62.      * @param argument
  63.      *            Argument on which to propagate the constraint
  64.      * @param other
  65.      *            Other argument in the sum
  66.      * @param sum
  67.      *            Sum of the two arguments
  68.      */
  69.     private void propagateOnArgument(final IntVar argument, final IntVar other,
  70.             final IntVar sum) {

  71.         // The argument maximum shall not be greater than the difference between
  72.         // the "sum" maximum and the "other" minimum.
  73.         final IntValue newMax = IntValue.diff(sum.getMaxValue(),
  74.                 other.getMinValue());
  75.         final boolean maxChanged = argument.reduceWithMaxValue(newMax);

  76.         // The argument minimum shall not be lesser than the difference between
  77.         // the "sum" minimum and the "other" maximum.
  78.         final IntValue newMin = IntValue.diff(sum.getMinValue(),
  79.                 other.getMaxValue());
  80.         final boolean minChanged = argument.reduceWithMinValue(newMin);

  81.         if (maxChanged || minChanged) {
  82.             addRecentChangedVariable(argument);
  83.         }
  84.     }

  85.     /**
  86.      * Get the first argument of the constraint.
  87.      * @return First argument
  88.      */
  89.     protected IntVar getFirst() {
  90.         return (IntVar) getFirstVariable();
  91.     }

  92.     /**
  93.      * Get the second argument of the constraint.
  94.      * @return Second argument
  95.      */
  96.     protected IntVar getSecond() {
  97.         return (IntVar) getSecondVariable();
  98.     }

  99.     /**
  100.      * Get the sum.
  101.      * @return Sum (third variable)
  102.      */
  103.     protected IntVar getSum() {
  104.         return (IntVar) getThirdVariable();
  105.     }

  106. }