package LBJ2.infer;
/**
* Represents a double implication between two propositional constraints.
*
* @author Nick Rizzolo
**/
public class PropositionalDoubleImplication
extends PropositionalBinaryConstraint
{
/**
* Initializing constructor.
*
* @param l The constraint on the left of the operator.
* @param r The constraint on the right of the operator.
**/
public PropositionalDoubleImplication(PropositionalConstraint l,
PropositionalConstraint r) {
super(l, r);
}
/** Determines whether the constraint is satisfied. */
public boolean evaluate() { return left.evaluate() == right.evaluate(); }
/**
* Produces a new, logically simplified version of this constraint,
* preserving variable consolidation.
*
* @see Constraint#consolidateVariables(java.util.AbstractMap)
* @return A logically simplified version of this constraint.
**/
public PropositionalConstraint simplify() {
return
new PropositionalConjunction(
new PropositionalDisjunction(left.negate(), right),
new PropositionalDisjunction(right.negate(), left)).simplify();
}
/**
* Produces a new propositional constraint equivalent to this constraint
* and that contains no negated constraints other than variables.
*
* @return A constraint representing the negation of this constraint.
**/
public PropositionalConstraint negate() {
return
new PropositionalConjunction(
new PropositionalDisjunction(left.negate(), right.negate()),
new PropositionalDisjunction(left, right));
}
/**
* Produces a new, logically simplified version of this constraint in
* conjunctive normal form (CNF).
*
* @return The conjunctive normal form of this constraint.
**/
public PropositionalConstraint CNF() {
return
new PropositionalConjunction(
new PropositionalDisjunction(
new PropositionalNegation(left),
right),
new PropositionalDisjunction(
new PropositionalNegation(right),
left))
.CNF();
}
/**
* Produces a new, logically simplified version of this constraint in
* disjunctive normal form (DNF).
*
* @return The disjunctive normal form of this constraint.
**/
public PropositionalConstraint DNF() {
return
new PropositionalDisjunction(
new PropositionalConjunction(left, right),
new PropositionalConjunction(
new PropositionalNegation(left),
new PropositionalNegation(right)))
.DNF();
}
/**
* Compares topology to determine if this constraint is more general than
* the given constraint; <i>note: this method is not required to be correct
* when it answers <code>false</code></i>.
*
* @param c The given constraint.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more general than the given constraint.
**/
public boolean moreGeneralThan(PropositionalConstraint c) {
return c.moreSpecificThan(this);
}
/**
* Compares topology to determine if this constraint is more specific than
* the given implication; <i>note: this method is not required to be
* correct when it answers <code>false</code></i>.
*
* @param c The given implication.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given implication.
**/
public boolean moreSpecificThan(PropositionalImplication c) {
PropositionalConstraint[] children =
(PropositionalConstraint[]) c.getChildren();
return left.equals(children[0]) && right.equals(children[1])
|| left.equals(children[1]) && right.equals(children[0]);
}
/**
* Compares topology to determine if this constraint is more specific than
* the given double implication; <i>note: this method is not required to be
* correct when it answers <code>false</code></i>.
*
* @param c The given double implication.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given double implication.
**/
public boolean moreSpecificThan(PropositionalDoubleImplication c) {
return false;
}
/**
* Compares topology to determine if this constraint is more specific than
* the given conjunction; <i>note: this method is not required to be
* correct when it answers <code>false</code></i>.
*
* @param c The given conjunction.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given conjunction.
**/
public boolean moreSpecificThan(PropositionalConjunction c) {
return false;
}
/**
* Compares topology to determine if this constraint is more specific than
* the given disjunction; <i>note: this method is not required to be
* correct when it answers <code>false</code></i>.
*
* @param c The given disjunction.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given disjunction.
**/
public boolean moreSpecificThan(PropositionalDisjunction c) {
PropositionalConstraint[] children =
(PropositionalConstraint[]) c.getChildren();
return children.length == 2
&& (new PropositionalNegation(left).equals(children[0])
&& right.equals(children[1])
|| new PropositionalNegation(left).equals(children[1])
&& right.equals(children[0])
|| left.equals(children[0])
&& new PropositionalNegation(right).equals(children[1])
|| left.equals(children[1])
&& new PropositionalNegation(right).equals(children[0]));
}
/**
* Compares topology to determine if this constraint is more specific than
* the given at-least; <i>note: this method is not required to be correct
* when it answers <code>false</code></i>.
*
* @param c The given at-least.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given disjunction.
**/
public boolean moreSpecificThan(PropositionalAtLeast c) {
return false;
}
/**
* Compares topology to determine if this constraint is more specific than
* the given negation; <i>note: this method is not required to be correct
* when it answers <code>false</code></i>.
*
* @param c The given negation.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given negation.
**/
public boolean moreSpecificThan(PropositionalNegation c) {
return false;
}
/**
* Compares topology to determine if this constraint is more specific than
* the given variable; <i>note: this method is not required to be correct
* when it answers <code>false</code></i>.
*
* @param c The given variable.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given variable.
**/
public boolean moreSpecificThan(PropositionalVariable c) {
return false;
}
/**
* Compares topology to determine if this constraint is more specific than
* the given constant; <i>note: this method is not required to be correct
* when it answers <code>false</code></i>.
*
* @param c The given constant.
* @return <code>true</code> if a topological analysis determined that this
* constraint is more specific than the given constant.
**/
public boolean moreSpecificThan(PropositionalConstant c) {
return c.evaluate();
}
/**
* The hash code of a <code>PropositionalDoubleImplication</code> is the
* sum of the hash codes of its children plus three.
*
* @return The hash code for this
* <code>PropositionalDoubleImplication</code>.
**/
public int hashCode() { return left.hashCode() + right.hashCode() + 3; }
/**
* Two <code>PropositionalDoubleImplication</code>s are equivalent when
* they are topologically equivalent, respecting the commutativity of
* double implication.
*
* @return <code>true</code> iff the argument is an equivalent
* <code>PropositionalDoubleImplication</code>.
**/
public boolean equals(Object o) {
if (!(o instanceof PropositionalDoubleImplication)) return false;
PropositionalDoubleImplication i = (PropositionalDoubleImplication) o;
return left.equals(i.left) && right.equals(i.right)
|| left.equals(i.right) && right.equals(i.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); }
/**
* Creates a string respresentation of this constraint using the string
* representations of the objects involved.
*
* @param buffer The output of this method will be appended to this buffer.
**/
public void write(StringBuffer buffer) {
buffer.append("(");
left.write(buffer);
buffer.append(" <=> ");
right.write(buffer);
buffer.append(")");
}
}