package LBJ2.infer; import java.util.Vector; import LBJ2.classify.Score; /** * Represents the comparison of two classifier applications. * * @author Nick Rizzolo **/ public class FirstOrderEqualityWithVariable extends FirstOrderEquality { /** The variable on the left of the equality. */ protected FirstOrderVariable left; /** The classifier application on the right of the equality. */ protected FirstOrderVariable right; /** * Initializing constructor. * * @param e Indicates whether this is an equality or an inequality. * @param l The left classifier application. * @param r The right classifier application. **/ public FirstOrderEqualityWithVariable(boolean e, FirstOrderVariable l, FirstOrderVariable r) { this(e, l, r, null); } /** * This constructor specifies a variable setter for when this equality is * quantified. * * @param e Indicates whether this is an equality or an inequality. * @param l The left classifier application. * @param r The right classifier application. * @param ear An argument replacer. **/ public FirstOrderEqualityWithVariable(boolean e, FirstOrderVariable l, FirstOrderVariable r, EqualityArgumentReplacer ear) { super(e, ear); left = l; right = r; } /** * Replaces all unquantified variables with the unique copy stored as a * value of the given map; also instantiates all quantified variables and * stores them in the given map. * * @param m The map in which to find unique copies of the variables. **/ public void consolidateVariables(java.util.AbstractMap m) { variableMap = m; if (m.containsKey(left)) left = (FirstOrderVariable) m.get(left); else m.put(left, left); if (m.containsKey(right)) right = (FirstOrderVariable) m.get(right); else m.put(right, right); } /** * This method sets the given quantification variables to the given object * references and evaluates the expressions involving those variables in * this constraint's <code>FirstOrderEquality</code> children. * * @param o The new object references for the enclosing quantification * variables, in order of nesting. **/ public void setQuantificationVariables(Vector o) { if (replacer == null) { System.err.println( "LBJ ERROR: Attempting to set quantification variable in " + "FirstOrderEqualityWithVariable with no variable setter " + "implementation provided."); System.exit(1); } replacer.setQuantificationVariables(o); if (!replacer.leftConstant) { left = new FirstOrderVariable(left.getClassifier(), replacer.getLeftObject()); if (variableMap != null && variableMap.containsKey(left)) left = (FirstOrderVariable) variableMap.get(left); } if (!replacer.rightConstant) { right = new FirstOrderVariable(right.getClassifier(), replacer.getRightObject()); if (variableMap != null && variableMap.containsKey(right)) right = (FirstOrderVariable) variableMap.get(right); } } /** Determines whether the constraint is satisfied. */ public boolean evaluate() { return equality == left.getValue().equals(right.getValue()); } /** * Transforms this first order constraint into a propositional constraint. * * @return The propositionalized constraint. **/ public PropositionalConstraint propositionalize() { Score[] leftScores = left.getScores().toArray(); Score[] rightScores = right.getScores().toArray(); if (leftScores.length == 0 || rightScores.length == 0) return new PropositionalConstant(false); if (leftScores.length == 1 && rightScores.length == 1) return new PropositionalConstant(leftScores[0].value .equals(rightScores[0].value)); PropositionalVariable[] leftVariables = new PropositionalVariable[leftScores.length]; PropositionalVariable[] rightVariables = new PropositionalVariable[rightScores.length]; int size = 0; for (int i = 0; i < leftScores.length; ++i) { boolean found = false; for (int j = 0; j < rightScores.length && !found; ++j) { if (!leftScores[i].value.equals(rightScores[j].value)) continue; found = true; leftVariables[size] = new PropositionalVariable(left.getClassifier(), left.getExample(), leftScores[i].value); rightVariables[size] = new PropositionalVariable(right.getClassifier(), right.getExample(), rightScores[j].value); ++size; } } if (size == 0) return new PropositionalConstant(false); if (equality && size == leftScores.length && size == rightScores.length) --size; PropositionalConstraint rightVariable = rightVariables[0]; if (!equality) rightVariable = new PropositionalNegation(rightVariable); PropositionalConstraint result = new PropositionalDisjunction( new PropositionalNegation(leftVariables[0]), rightVariable); if (equality) result = new PropositionalConjunction( result, new PropositionalDisjunction( new PropositionalNegation(rightVariable), leftVariables[0])); for (int i = 1; i < size; ++i) { rightVariable = rightVariables[i]; if (!equality) rightVariable = new PropositionalNegation(rightVariable); result = new PropositionalConjunction( result, new PropositionalDisjunction( new PropositionalNegation(leftVariables[i]), rightVariable)); if (equality) result = new PropositionalConjunction( result, new PropositionalDisjunction( new PropositionalNegation(rightVariable), leftVariables[i])); } return result; } /** * The hash code of a <code>FirstOrderEqualityWithVariable</code> is the * sum of the hash codes of its children plus 2. * * @return The hash code for this * <code>FirstOrderEqualityWithVariable</code>. **/ public int hashCode() { if (replacer != null) return replacer.hashCode(); return left.hashCode() + right.hashCode() + 2; } /** * Two <code>FirstOrderEqualityWithVariable</code>s are equivalent when * their children are equivalent in either order. * * @return <code>true</code> iff the argument is a * <code>FirstOrderEqualityWithVariable</code> involving the same * variables. **/ public boolean equals(Object o) { if (!(o instanceof FirstOrderEqualityWithVariable)) return false; FirstOrderEqualityWithVariable n = (FirstOrderEqualityWithVariable) o; return replacer == n.replacer && (replacer != null || replacer == null && (left.equals(n.left) && right.equals(n.right) || left.equals(n.right) && right.equals(n.left))); } /** * Calls the appropriate <code>visit(·)</code> method of the given * <code>Inference</code> for this <code>Constraint</code>, as per the * visitor pattern. * * @param infer The inference visiting this constraint. **/ public void runVisit(Inference infer) { infer.visit(this); } }