package LBJ2.infer; import java.util.Collection; import java.util.Iterator; import java.util.Vector; /** * An "at least" quantifier states that the constraint must hold for at least * <i>m</i> of the objects in the collection. * * @author Nick Rizzolo **/ public class AtLeastQuantifier extends Quantifier { /** The number of objects for which the constraint must hold. */ protected int m; /** * Initializing constructor. * * @param q The name of the quantification variable. * @param col The collection of objects to iterate over. * @param con The constraint being quantified. * @param m The number of objects for which the constraint must hold. **/ public AtLeastQuantifier(String q, Collection col, FirstOrderConstraint con, int m) { this(q, col, con, m, null); } /** * This constructor specifies a variable setter for when this quantifier is * itself quantified. * * @param q The name of the quantification variable. * @param col The collection of objects to iterate over. * @param con The constraint being quantified. * @param m The number of objects for which the constraint must hold. * @param qar The variable setter. **/ public AtLeastQuantifier(String q, Collection col, FirstOrderConstraint con, int m, QuantifierArgumentReplacer qar) { super(q, col, con, qar); this.m = Math.max(m, 0); } /** Determines whether the constraint is satisfied. */ public boolean evaluate() { int satisfied = 0; int index = initialize(); for (Iterator I = collection.iterator(); I.hasNext() && satisfied < m; ) { enclosingQuantificationSettings.set(index, I.next()); constraint.setQuantificationVariables(enclosingQuantificationSettings); if (constraint.evaluate()) ++satisfied; } enclosingQuantificationSettings.removeElementAt(index); return satisfied == m; } /** * This method sets the given quantification variables to the given object * references and evaluates the expressions involving those variables in * this constraint's children. * * @param o The new object references for the enclosing quantification * variables, in order of nesting. **/ public void setQuantificationVariables(Vector o) { enclosingQuantificationSettings = o; if (replacer != null) { replacer.setQuantificationVariables(o); if (!replacer.collectionConstant) collection = replacer.getCollection(); if (!replacer.boundConstant) m = replacer.getBound(); } } /** * Transforms this first order constraint into a propositional constraint. * * @return The propositionalized constraint. **/ public PropositionalConstraint propositionalize() { if (collection.size() < m) return new PropositionalConstant(false); if (m == 0) return new PropositionalConstant(true); PropositionalConstraint[] pc = new PropositionalConstraint[collection.size()]; int index = initialize(); int i = 0; for (Iterator I = collection.iterator(); I.hasNext(); ++i) { enclosingQuantificationSettings.set(index, I.next()); constraint.setQuantificationVariables(enclosingQuantificationSettings); pc[i] = constraint.propositionalize(); } enclosingQuantificationSettings.removeElementAt(index); if (pc.length == 1) return pc[0]; return new PropositionalAtLeast(pc, m); } /** * The hash code of a <code>AtLeastQuantifier</code> is the sum of the hash * codes of its children plus one. * * @return The hash code for this <code>AtLeastQuantifier</code>. **/ public int hashCode() { return super.hashCode() + m + 1; } /** * Two <code>AtLeastQuantifier</code>s are equivalent when their children * are equivalent. * * @return <code>true</code> iff the argument is an equivalent * <code>AtLeastQuantifier</code>. **/ public boolean equals(Object o) { if (!(o instanceof AtLeastQuantifier)) return false; AtLeastQuantifier q = (AtLeastQuantifier) o; return super.equals(q) && m == q.m; } /** * 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); } }