package aima.core.logic.propositional.visitors;
import aima.core.logic.propositional.parsing.AbstractPLVisitor;
import aima.core.logic.propositional.parsing.ast.ComplexSentence;
import aima.core.logic.propositional.parsing.ast.Connective;
import aima.core.logic.propositional.parsing.ast.Sentence;
/**
* Artificial Intelligence A Modern Approach (3rd Edition): page 249.<br>
* <br>
* Distributivity of | over &:<br>
* (α | (β & γ))<br>
* ≡<br>
* ((α | β) & (α | γ))<br>
*
* @author Ciaran O'Reilly
*
*/
public class DistributeOrOverAnd extends AbstractPLVisitor<Object> {
/**
* Distribute or (|) over and (&).
*
* @param sentence
* a propositional logic sentence. This sentence should already
* have biconditionals, and implications removed and negations
* moved inwards.
* @return an equivalent Sentence to the input with or's distributed over
* and's.
*/
public static Sentence distribute(Sentence sentence) {
Sentence result = null;
DistributeOrOverAnd distributeOrOverAnd = new DistributeOrOverAnd();
result = sentence.accept(distributeOrOverAnd, null);
return result;
}
@Override
public Sentence visitBinarySentence(ComplexSentence s, Object arg) {
Sentence result = null;
if (s.isOrSentence()) {
Sentence s1 = s.getSimplerSentence(0).accept(this, arg);
Sentence s2 = s.getSimplerSentence(1).accept(this, arg);
if (s1.isAndSentence() || s2.isAndSentence()) {
Sentence alpha, betaAndGamma;
if (s2.isAndSentence()) {
// (α | (β & γ))
// Note: even if both are 'and' sentence
// we will prefer to use s2
alpha = s1;
betaAndGamma = s2;
} else {
// Note: Need to handle this case too
// ((β & γ) | α)
alpha = s2;
betaAndGamma = s1;
}
Sentence beta = betaAndGamma.getSimplerSentence(0);
Sentence gamma = betaAndGamma.getSimplerSentence(1);
if (s2.isAndSentence()) {
// ((α | β) & (α | γ))
Sentence alphaOrBeta = (new ComplexSentence(Connective.OR,
alpha, beta)).accept(this, null);
Sentence alphaOrGamma = (new ComplexSentence(Connective.OR,
alpha, gamma)).accept(this, null);
result = new ComplexSentence(Connective.AND, alphaOrBeta,
alphaOrGamma);
} else {
// ((β | α) & (γ | α))
Sentence betaOrAlpha = (new ComplexSentence(Connective.OR,
beta, alpha)).accept(this, null);
Sentence gammaOrAlpha = (new ComplexSentence(Connective.OR,
gamma, alpha)).accept(this, null);
result = new ComplexSentence(Connective.AND, betaOrAlpha,
gammaOrAlpha);
}
} else {
result = new ComplexSentence(Connective.OR, s1, s2);
}
} else {
result = super.visitBinarySentence(s, arg);
}
return result;
}
}