package aima.core.logic.fol.inference;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Set;
import aima.core.logic.fol.inference.proof.ProofStepClauseDemodulation;
import aima.core.logic.fol.kb.data.Clause;
import aima.core.logic.fol.kb.data.Literal;
import aima.core.logic.fol.parsing.ast.AtomicSentence;
import aima.core.logic.fol.parsing.ast.Term;
import aima.core.logic.fol.parsing.ast.TermEquality;
import aima.core.logic.fol.parsing.ast.Variable;
/**
* Artificial Intelligence A Modern Approach (3rd Edition): page 354.<br>
* <br>
* Demodulation: For any terms x, y, and z, where z appears somewhere in literal
* m<sub>i</sub> and where UNIFY(x,z) = θ:<br>
*
* <pre>
* x=y, m<sub>1</sub> OR ... OR m<sub>n</sub>[z]
* ------------------------------------------------------------
* SUB(SUBST(θ,x), SUBST(θ,y), m<sub>1</sub> OR ... OR m<sub>n</sub>)
* </pre>
*
* where SUBST is the usual substitution of a binding list, and SUB(x,y,m) means
* to replace x with y everywhere that x occurs within m.<br>
* <br>
* Some additional restrictions/clarifications highlighted in:<br>
* <a href="http://logic.stanford.edu/classes/cs157/2008/lectures/lecture15.pdf"
* >Demodulation Restrictions</a> <br>
* 1. Unit Equations Only.<br>
* 2. Variables substituted in Equation Only.<br>
*
* @author Ciaran O'Reilly
*
*/
public class Demodulation extends AbstractModulation {
public Demodulation() {
}
public Clause apply(TermEquality assertion, Clause clExpression) {
Clause altClExpression = null;
for (Literal l1 : clExpression.getLiterals()) {
AtomicSentence altExpression = apply(assertion,
l1.getAtomicSentence());
if (null != altExpression) {
// I have an alternative, create a new clause
// with the alternative and return
List<Literal> newLits = new ArrayList<Literal>();
for (Literal l2 : clExpression.getLiterals()) {
if (l1.equals(l2)) {
newLits.add(l1.newInstance(altExpression));
} else {
newLits.add(l2);
}
}
// Only apply demodulation at most once on
// each call.
altClExpression = new Clause(newLits);
altClExpression.setProofStep(new ProofStepClauseDemodulation(
altClExpression, clExpression, assertion));
if (clExpression.isImmutable()) {
altClExpression.setImmutable();
}
if (!clExpression.isStandardizedApartCheckRequired()) {
altClExpression.setStandardizedApartCheckNotRequired();
}
break;
}
}
return altClExpression;
}
public AtomicSentence apply(TermEquality assertion,
AtomicSentence expression) {
AtomicSentence altExpression = null;
IdentifyCandidateMatchingTerm icm = getMatchingSubstitution(
assertion.getTerm1(), expression);
if (null != icm) {
Term replaceWith = substVisitor.subst(
icm.getMatchingSubstitution(), assertion.getTerm2());
// Want to ignore reflexivity axiom situation, i.e. x = x
if (!icm.getMatchingTerm().equals(replaceWith)) {
ReplaceMatchingTerm rmt = new ReplaceMatchingTerm();
// Only apply demodulation at most once on each call.
altExpression = rmt.replace(expression, icm.getMatchingTerm(),
replaceWith);
}
}
return altExpression;
}
//
// PROTECTED METHODS
//
@Override
protected boolean isValidMatch(Term toMatch,
Set<Variable> toMatchVariables, Term possibleMatch,
Map<Variable, Term> substitution) {
// Demodulation only allows substitution in the equation only,
// if the substitution contains variables not in the toMatch
// side of the equation (i.e. left hand side), then
// it is not a legal demodulation match.
// Note: see:
// http://logic.stanford.edu/classes/cs157/2008/lectures/lecture15.pdf
// slide 23 for an example.
if (toMatchVariables.containsAll(substitution.keySet())) {
return true;
}
return false;
}
}