/*******************************************************************************
* Copyright 2014 Felipe Takiyama
*
* Licensed 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 br.usp.poli.takiyama.common;
import java.util.Set;
import br.usp.poli.takiyama.prv.Binding;
import br.usp.poli.takiyama.prv.LogicalVariable;
import br.usp.poli.takiyama.prv.Replaceable;
import br.usp.poli.takiyama.prv.Substitution;
import br.usp.poli.takiyama.prv.Term;
/**
* This class represents constraints of the form X ? Y, where
* X and Y are {@link Term}s and ? is an comparison operator. For now,
* only operators '=' and '≠' are supported.
* <p>
* A note concerning {@link #equals}: constraints X ? Y and Y ? X should
* be considered the same, unless '?' is not symmetric.
* </p>
*
* @author Felipe Takiyama
*
*/
public interface Constraint extends Replaceable<Constraint> {
/**
* Returns the left-hand side of this constraint.
*
* @return the left-hand side of this constraint.
*/
public Term firstTerm();
/**
* Returns the right-hand side of this constraint.
*
* @return the right-hand side of this constraint.
*/
public Term secondTerm();
/**
* Applies the substitution in this constraint.
* <p>
* If the resulting constraint is always false (for instance, q ≠ q),
* then throws an {@link IllegalArgumentException}.
* </p>
* <p>
* If the specified substitution does not apply to this constraint, then
* returns this constraint unchanged.
* </p>
*
* @param s The substitution to apply on the constraint
* @return The constraint that results from the application of the
* specified substitution to this constraint, following the rules
* specified above.
* @throws IllegalArgumentException if the resulting constraint is
* always false
* @throws IllegalStateException If the resulting constraint involves only
* constants
*/
public Constraint apply(Substitution s) throws IllegalArgumentException,
IllegalStateException;
/**
* Returs <code>true</code> if the specified term is in the constraint
*
* @param t The term to check the existence
* @return <code>true</code> if the term specified equals one of the
* terms in this constraint, <code>false</code>.
*/
public boolean contains(Term t);
/**
* Returns <code>true</code> if this constraint and the specified
* constraint have a common term.
*
* @param c The constraint to compare to.
* @return <code>true</code> if the constraints have a common term,
* <code>false</code> otherwise.
*/
public boolean hasCommonTerm(Constraint c);
/**
* Returns <code>true</code> if the specified {@link Binding} satisfies this
* constraint. In other words, returns <code>true</code> if applying
* the specified binding to this constraint results in a valid sentence.
* <p>
* This method also returns <code>false</code> when it is not possible to
* evaluate whether the resulting constraint is valid or not.
* </p>
* <p>
* For instance, let X, Y, W and Z be logical variables with D(X) = D(Y) =
* D(W) = D(Z) = {a, b,..., z}. Then:
* <li> X != a is consistent with X/b (because b != a is true)
* <li> X != Y is consistent with W/Z (because X != Y is still true)
* <li> X != a is not consistent with X/a (because a != a is not true)
* <li> X != a is not consistent with X/W (because W != a is not necessarily
* true)
* <li> X != Y is not consistent with X/W (because W != Y is not necessarily
* true)
* <li> X == Y is consistent with W/Z (because X == Y is still true)
* <li> X == a is consistent with X/a (because a == a is true)
* <li> X == a is consistent with X/W (because X = a & X = W implies W = a)
* <li> X == Y is consistent with X/W (because X = Y & X = W implies W = Y)
* <li> X == a is not consistent with X/b (because b == a is not true)
* </p>
*
* @param b The binding to test
* @return <code>true</code> if this constraint is consistent with the
* specified binding, <code>false</code> otherwise.
*/
public boolean isConsistentWith(Binding b);
/**
* Returns the {@link Binding} corresponding to this constraint. That is,
* if this constraint is t1 ≠ t2, then this method returns the
* binding t1/t2.
*
* @return The Binding corresponding to this constraint.
* @throws IllegalArgumentException If the first term is not a Logical
* Variable. In this case it is not possible to create the binding.
*/
public Binding toBinding();
/**
* Returns the {@link Binding} obtained by inverting the terms of this
* constraint.
* That is, if this constraint is t2 ≠ t2, then this method returns
* the binding t2/t1.
*
* @return The inverse binding corresponding to this constraint.
* @throws IllegalArgumentException If the second term is not a Logical
* Variable. In this case it is not possible to create the binding.
*/
public Binding toInverseBinding();
/**
* Returns <code>true</code> if this constraint is unary, that is, if
* it is composed by a logical variable and a constant.
*
* @return <code>true</code> if this constraint is unary, <code>false</code>
* otherwise.
*/
public boolean isUnary();
/**
* Returns a set containing all logical variables in this constraint. Note
* that this set has a maximum size of 2.
*
* @return A set containing all logical variables in this constraint
*/
public Set<LogicalVariable> logicalVariables();
@Override
public boolean equals(Object o);
@Override
public int hashCode();
@Override
public String toString();
}