package aima.test.core.unit.logic.propositional.algorithms; import java.util.List; import org.junit.Assert; import org.junit.Before; import org.junit.Test; import aima.core.logic.propositional.algorithms.DPLL; import aima.core.logic.propositional.algorithms.KnowledgeBase; import aima.core.logic.propositional.algorithms.Model; import aima.core.logic.propositional.parsing.PEParser; import aima.core.logic.propositional.parsing.ast.Sentence; import aima.core.logic.propositional.parsing.ast.Symbol; import aima.core.logic.propositional.visitors.CNFClauseGatherer; import aima.core.logic.propositional.visitors.CNFTransformer; import aima.core.logic.propositional.visitors.SymbolCollector; import aima.core.util.Converter; /** * @author Ravi Mohan * */ public class DPLLTest { private DPLL dpll; private PEParser parser; @Before public void setUp() { parser = new PEParser(); dpll = new DPLL(); } @Test public void testDPLLReturnsTrueWhenAllClausesTrueInModel() { Model model = new Model(); model = model.extend(new Symbol("A"), true).extend(new Symbol("B"), true); Sentence sentence = (Sentence) parser.parse("((A AND B) AND (A OR B))"); boolean satisfiable = dpll.dpllSatisfiable(sentence, model); Assert.assertEquals(true, satisfiable); } @Test public void testDPLLReturnsFalseWhenOneClauseFalseInModel() { Model model = new Model(); model = model.extend(new Symbol("A"), true).extend(new Symbol("B"), false); Sentence sentence = (Sentence) parser.parse("((A OR B) AND (A => B))"); boolean satisfiable = dpll.dpllSatisfiable(sentence, model); Assert.assertEquals(false, satisfiable); } @Test public void testDPLLFiltersClausesTheStatusOfWhichAreKnown() { Model model = new Model(); model = model.extend(new Symbol("A"), true).extend(new Symbol("B"), true); Sentence sentence = (Sentence) parser .parse("((A AND B) AND (B AND C))"); List<Sentence> clauseList = new Converter<Sentence>() .setToList(new CNFClauseGatherer() .getClausesFrom(new CNFTransformer() .transform(sentence))); List<Sentence> clausesWithNonTrueValues = dpll .clausesWithNonTrueValues(clauseList, model); Assert.assertEquals(1, clausesWithNonTrueValues.size()); Sentence nonTrueClause = (Sentence) parser.parse("(B AND C)"); clausesWithNonTrueValues.contains(nonTrueClause); } @Test public void testDPLLFilteringNonTrueClausesGivesNullWhenAllClausesAreKnown() { Model model = new Model(); model = model.extend(new Symbol("A"), true) .extend(new Symbol("B"), true).extend(new Symbol("C"), true); Sentence sentence = (Sentence) parser .parse("((A AND B) AND (B AND C))"); List<Sentence> clauseList = new Converter<Sentence>() .setToList(new CNFClauseGatherer() .getClausesFrom(new CNFTransformer() .transform(sentence))); List<Sentence> clausesWithNonTrueValues = dpll .clausesWithNonTrueValues(clauseList, model); Assert.assertEquals(0, clausesWithNonTrueValues.size()); } @Test public void testDPLLFindsPurePositiveSymbolsWhenTheyExist() { Model model = new Model(); model = model.extend(new Symbol("A"), true).extend(new Symbol("B"), true); Sentence sentence = (Sentence) parser .parse("((A AND B) AND (B AND C))"); List<Sentence> clauseList = new Converter<Sentence>() .setToList(new CNFClauseGatherer() .getClausesFrom(new CNFTransformer() .transform(sentence))); List<Symbol> symbolList = new Converter<Symbol>() .setToList(new SymbolCollector().getSymbolsIn(sentence)); DPLL.SymbolValuePair sv = dpll.findPureSymbolValuePair(clauseList, model, symbolList); Assert.assertNotNull(sv); Assert.assertEquals(new Symbol("C"), sv.symbol); Assert.assertEquals(new Boolean(true), sv.value); } @Test public void testDPLLFindsPureNegativeSymbolsWhenTheyExist() { Model model = new Model(); model = model.extend(new Symbol("A"), true).extend(new Symbol("B"), true); Sentence sentence = (Sentence) parser .parse("((A AND B) AND ( B AND (NOT C) ))"); List<Sentence> clauseList = new Converter<Sentence>() .setToList(new CNFClauseGatherer() .getClausesFrom(new CNFTransformer() .transform(sentence))); List<Symbol> symbolList = new Converter<Symbol>() .setToList(new SymbolCollector().getSymbolsIn(sentence)); DPLL.SymbolValuePair sv = dpll.findPureSymbolValuePair(clauseList, model, symbolList); Assert.assertNotNull(sv); Assert.assertEquals(new Symbol("C"), sv.symbol); Assert.assertEquals(new Boolean(false), sv.value); } @Test public void testDPLLSucceedsWithAandNotA() { Sentence sentence = (Sentence) parser.parse("(A AND (NOT A))"); boolean satisfiable = dpll.dpllSatisfiable(sentence); Assert.assertEquals(false, satisfiable); } @Test public void testDPLLSucceedsWithChadCarffsBugReport() { KnowledgeBase kb = new KnowledgeBase(); kb.tell("(B12 <=> (P11 OR (P13 OR (P22 OR P02))))"); kb.tell("(B21 <=> (P20 OR (P22 OR (P31 OR P11))))"); kb.tell("(B01 <=> (P00 OR (P02 OR P11)))"); kb.tell("(B10 <=> (P11 OR (P20 OR P00)))"); kb.tell("(NOT B21)"); kb.tell("(NOT B12)"); kb.tell("(B10)"); kb.tell("(B01)"); Assert.assertTrue(kb.askWithDpll("(P00)")); Assert.assertFalse(kb.askWithDpll("(NOT P00)")); } @Test public void testDPLLSucceedsWithStackOverflowBugReport1() { Sentence sentence = (Sentence) parser .parse("((A OR (NOT A)) AND (A OR B))"); Assert.assertTrue(dpll.dpllSatisfiable(sentence)); } @Test public void testDPLLSucceedsWithChadCarffsBugReport2() { KnowledgeBase kb = new KnowledgeBase(); kb.tell("(B10 <=> (P11 OR (P20 OR P00)))"); kb.tell("(B01 <=> (P00 OR (P02 OR P11)))"); kb.tell("(B21 <=> (P20 OR (P22 OR (P31 OR P11))))"); kb.tell("(B12 <=> (P11 OR (P13 OR (P22 OR P02))))"); kb.tell("(NOT B21)"); kb.tell("(NOT B12)"); kb.tell("(B10)"); kb.tell("(B01)"); Assert.assertTrue(kb.askWithDpll("(P00)")); Assert.assertFalse(kb.askWithDpll("(NOT P00)")); } @Test public void testIssue66() { // http://code.google.com/p/aima-java/issues/detail?id=66 Model model = new Model(); model = model.extend(new Symbol("A"), false) .extend(new Symbol("B"), false).extend(new Symbol("C"), true); Sentence sentence = (Sentence) parser.parse("((A OR B) OR C)"); Assert.assertTrue(dpll.dpllSatisfiable(sentence, model)); } @Test public void testDoesNotKnow() { KnowledgeBase kb = new KnowledgeBase(); kb.tell("A"); Assert.assertFalse(kb.askWithDpll("B")); Assert.assertFalse(kb.askWithDpll("(NOT B)")); } }