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 DistributeAndOverOr extends AbstractPLVisitor<Object> {
/**
* Distribute and (&) over or (|).
*
* @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 and's distributed over
* or's.
*/
public static Sentence distribute(Sentence sentence) {
Sentence result = null;
DistributeAndOverOr distributeAndOverOr = new DistributeAndOverOr();
result = sentence.accept(distributeAndOverOr, null);
return result;
}
@Override
public Sentence visitBinarySentence(ComplexSentence s, Object arg) {
Sentence result = null;
if (s.isAndSentence()) {
Sentence s1 = s.getSimplerSentence(0).accept(this, arg);
Sentence s2 = s.getSimplerSentence(1).accept(this, arg);
if (s1.isOrSentence() || s2.isOrSentence()) {
Sentence alpha, betaAndGamma;
if (s2.isOrSentence()) {
// (α & (β | γ))
// Note: even if both are 'or' 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.isOrSentence()) {
// ((α & β) | (α & γ))
Sentence alphaAndBeta = (new ComplexSentence(Connective.AND,
alpha, beta)).accept(this, null);
Sentence alphaAndGamma = (new ComplexSentence(Connective.AND,
alpha, gamma)).accept(this, null);
result = new ComplexSentence(Connective.OR, alphaAndBeta,
alphaAndGamma);
} else {
// ((β & α) | (γ & α))
Sentence betaAndAlpha = (new ComplexSentence(Connective.AND,
beta, alpha)).accept(this, null);
Sentence gammaAndAlpha = (new ComplexSentence(Connective.AND,
gamma, alpha)).accept(this, null);
result = new ComplexSentence(Connective.OR, betaAndAlpha,
gammaAndAlpha);
}
} else {
result = new ComplexSentence(Connective.AND, s1, s2);
}
} else {
result = super.visitBinarySentence(s, arg);
}
return result;
}
}