001 package ifs.example.csp;
002
003 import ifs.model.*;
004 import java.util.*;
005
006 /**
007 * CSP binary constraint.
008 * <br><br>
009 * This class only implements the generation of a binary CSP constraint and the consistency check.
010 *
011 * @author <a href="mailto:muller@ktiml.mff.cuni.cz">Tomáš Müller</a>
012 * @version 1.0
013 */
014 public class CSPBinaryConstraint extends BinaryConstraint {
015 private int iId = 0;
016 private boolean iIsConsistent[][] = null;
017 private int iNrCompatiblePairs;
018
019 /** Constructor
020 * @param nrCompatiblePairs number of compatible pairs of values in the constraint
021 */
022 public CSPBinaryConstraint(int id, int nrCompatiblePairs) {
023 super();
024 iId = id;
025 iNrCompatiblePairs = nrCompatiblePairs;
026 }
027
028 private void swap(int[][] allPairs, int first, int second) {
029 int[] a = allPairs[first];
030 allPairs[first] = allPairs[second];
031 allPairs[second] = a;
032 }
033
034 /**
035 * Initializes the constraint. Randomly generates the given number of compatible pairs of values.
036 * @param rndNumGen random number generator
037 */
038 public void init(Random rndNumGen) {
039 int numberOfAllPairs = first().values().size() * second().values().size();
040 int[][] allPairs = new int[numberOfAllPairs][];
041 int idx = 0;
042
043 iIsConsistent = new boolean[first().values().size()][second().values().size()];
044
045 for (Enumeration i1=first().values().elements();
046 i1.hasMoreElements();) {
047 CSPValue v1 = (CSPValue)i1.nextElement();
048 for (Enumeration i2=second().values().elements();
049 i2.hasMoreElements();) {
050 CSPValue v2 = (CSPValue)i2.nextElement();
051 iIsConsistent[v1.toInt()][v2.toInt()] = false;
052 allPairs[idx++] = new int[] {v1.toInt(), v2.toInt()};
053 }
054 }
055
056 for (int i=0; i<iNrCompatiblePairs; i++) {
057 swap(allPairs, i, i+(int)(rndNumGen.nextDouble()*(numberOfAllPairs-i)));
058 iIsConsistent[allPairs[i][0]][allPairs[i][1]] = true;
059 }
060 }
061
062 /**
063 * True if the pair of given values is compatible.
064 */
065 public boolean isConsistent(Value value1, Value value2) {
066 if (value1==null || value2==null) return true;
067 if (isFirst(value1.variable())) {
068 return iIsConsistent[value1.toInt()][value2.toInt()];
069 } else {
070 return iIsConsistent[value2.toInt()][value1.toInt()];
071 }
072 }
073
074 /**
075 * Add the other variable to the set of conflicts, if it is not compatible with the given value.
076 */
077 public void computeConflicts(Value aValue, Set conflicts) {
078 if (isFirst(aValue.variable())) {
079 if (!isConsistent(aValue, second().getAssignment())) {
080 conflicts.add(second().getAssignment());
081 }
082 } else {
083 if (!isConsistent(first().getAssignment(), aValue)) {
084 conflicts.add(first().getAssignment());
085 }
086 }
087 }
088
089 public String getName() { return "C"+getId(); }
090 }