package aima.core.logic.propositional.visitors;
import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import aima.core.logic.propositional.kb.data.Clause;
import aima.core.logic.propositional.kb.data.Literal;
import aima.core.logic.propositional.parsing.ast.ComplexSentence;
import aima.core.logic.propositional.parsing.ast.PropositionSymbol;
import aima.core.logic.propositional.parsing.ast.Sentence;
/**
* Utility class for collecting clauses from CNF Sentences.
*
* @author Ravi Mohan
* @author Ciaran O'Reilly
*/
public class ClauseCollector extends BasicGatherer<Clause> {
/**
* Collect a set of clauses from a list of given sentences.
*
* @param cnfSentences
* a list of CNF sentences from which to collect clauses.
* @return a set of all contained clauses.
* @throws IllegalArgumentException
* if any of the given sentences are not in CNF.
*/
public static Set<Clause> getClausesFrom(Sentence... cnfSentences) {
Set<Clause> result = new LinkedHashSet<Clause>();
ClauseCollector clauseCollector = new ClauseCollector();
for (Sentence cnfSentence : cnfSentences) {
result = cnfSentence.accept(clauseCollector, result);
}
return result;
}
@Override
public Set<Clause> visitPropositionSymbol(PropositionSymbol s, Set<Clause> arg) {
// a positive unit clause
Literal positiveLiteral = new Literal(s);
arg.add(new Clause(positiveLiteral));
return arg;
}
@Override
public Set<Clause> visitUnarySentence(ComplexSentence s, Set<Clause> arg) {
if (!s.getSimplerSentence(0).isPropositionSymbol()) {
throw new IllegalStateException("Sentence is not in CNF: "+s);
}
// a negative unit clause
Literal negativeLiteral = new Literal((PropositionSymbol)s.getSimplerSentence(0), false);
arg.add(new Clause(negativeLiteral));
return arg;
}
@Override
public Set<Clause> visitBinarySentence(ComplexSentence s, Set<Clause> arg) {
if (s.isAndSentence()) {
s.getSimplerSentence(0).accept(this, arg);
s.getSimplerSentence(1).accept(this, arg);
} else if (s.isOrSentence()) {
List<Literal> literals = new ArrayList<Literal>(LiteralCollector.getLiterals(s));
arg.add(new Clause(literals));
} else {
throw new IllegalArgumentException("Sentence is not in CNF: "+s);
}
return arg;
}
//
// PRIVATE
//
private static class LiteralCollector extends BasicGatherer<Literal> {
private static Set<Literal> getLiterals(Sentence disjunctiveSentence) {
Set<Literal> result = new LinkedHashSet<Literal>();
LiteralCollector literalCollector = new LiteralCollector();
result = disjunctiveSentence.accept(literalCollector, result);
return result;
}
@Override
public Set<Literal> visitPropositionSymbol(PropositionSymbol s, Set<Literal> arg) {
// a positive literal
Literal positiveLiteral = new Literal(s);
arg.add(positiveLiteral);
return arg;
}
@Override
public Set<Literal> visitUnarySentence(ComplexSentence s, Set<Literal> arg) {
if (!s.getSimplerSentence(0).isPropositionSymbol()) {
throw new IllegalStateException("Sentence is not in CNF: "+s);
}
// a negative literal
Literal negativeLiteral = new Literal((PropositionSymbol)s.getSimplerSentence(0), false);
arg.add(negativeLiteral);
return arg;
}
@Override
public Set<Literal> visitBinarySentence(ComplexSentence s, Set<Literal> arg) {
if (s.isOrSentence()) {
s.getSimplerSentence(0).accept(this, arg);
s.getSimplerSentence(1).accept(this, arg);
} else {
throw new IllegalArgumentException("Sentence is not in CNF: "+s);
}
return arg;
}
}
}