CrossEqual.java
/* Copyright 2015 Laurent COCAULT
* Licensed to Laurent COCAULT under one or more contributor license agreements.
* See the NOTICE file distributed with this work for additional information
* regarding copyright ownership. Laurent COCAULT licenses this file to You
* under the Apache License, Version 2.0 (the "License"); you may not use this
* file except in compliance with the License. You may obtain a copy of the
* License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.csp.constraint.model.general;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import org.csp.constraint.model.UnsizedConstraint;
import org.csp.constraint.model.Value;
import org.csp.constraint.model.Variable;
/**
* Constraint specifying that associate variables from two different lists. When
* the a variable of one list has the expected value, the variable of the same
* index of the other list has the other expected value. Example : let's have
* two array of variables (A, B, C) and (D, E, F). The constraint can specify
* that when a variable of the first array has a value V1, the corresponding
* variable of the second array has a value V2. Suppose that during a
* propagation B take V1 as a value. Then the constraint will value E=V2.
*/
public class CrossEqual<T> extends UnsizedConstraint<T> {
/** Left array. */
private List<Variable<T>> left_;
/** Left value. */
private Value<T> leftValue_;
/** Right array. */
private List<Variable<T>> right_;
/** Right value. */
private Value<T> rightValue_;
/**
* Constructor.
* @param leftArray
* First array
* @param leftValue
* Expected value for the first array
* @param rightArray
* Second array
* @param rightValue
* Expected value for the second array
*/
public CrossEqual(final List<Variable<T>> leftArray,
final Value<T> leftValue, final List<Variable<T>> rightArray,
final Value<T> rightValue) {
super("CROSS_EQUAL", new ArrayList<Variable<T>>());
// Initialize attributes
left_ = leftArray;
leftValue_ = leftValue;
right_ = rightArray;
rightValue_ = rightValue;
// Both vector variables are implied in the constraint
addVariables(leftArray);
addVariables(rightArray);
}
/**
* {@inheritDoc}
*/
@Override
public void propagate() {
// Propagate in both ways
propagate(left_, leftValue_, right_, rightValue_);
propagate(right_, rightValue_, left_, leftValue_);
}
/**
* Propagate constraint in one way : check "from" variables and deduce
* possible values for "to" variables.
* @param from
* List of variables at the origin of the propagation
* @param fromValue
* Value at the origin of the propagation
* @param to
* List of variables to update
* @param toValue
* Value associated to the fromValue
*/
protected void propagate(final List<Variable<T>> from,
final Value<T> fromValue, final List<Variable<T>> to,
final Value<T> toValue) {
// Iterate with the index to find the corresponding variable in "to"
for (int index = 0; index < from.size(); index++) {
// Get the "from" variable
final Variable<T> var = from.get(index);
if (var.isBound() && var.getValue().equals(fromValue)) {
// When the "from" variable is bound with the expected value,
// the corresponding "to" variable should also be bound.
if (to.get(index).setValue(toValue)) {
addRecentChangedVariable(to.get(index));
}
} else if (!var.contains(fromValue)) {
// When the expected value is no more in the "from" variable
// domain, the corresponding "to" value must not be in the
// domain of the "to" variable.
if (to.get(index).removeValue(toValue)) {
addRecentChangedVariable(to.get(index));
}
}
}
}
/**
* {@inheritDoc}
*/
@Override
public String toString() {
// String builder
final StringBuilder builder = new StringBuilder();
// Display the constraint
builder.append("CROSS_EQUAL(" + leftValue_ + " in (");
Iterator<Variable<T>> vars = left_.iterator();
while (vars.hasNext()) {
// Display every variable
builder.append(vars.next().getName());
if (vars.hasNext()) {
// Next variable
builder.append(", ");
} else {
// Last variable
builder.append(") equals " + rightValue_ + " in (");
}
}
vars = right_.iterator();
while (vars.hasNext()) {
// Display every variable
builder.append(vars.next().getName());
if (vars.hasNext()) {
// Next variable
builder.append(", ");
} else {
// Last variable
builder.append("))");
}
}
return builder.toString();
}
}