001 package aima.test.logictest.foltest; 002 003 import java.util.HashSet; 004 import java.util.Set; 005 006 import aima.logic.fol.CNFConverter; 007 import aima.logic.fol.SubsumptionElimination; 008 import aima.logic.fol.domain.FOLDomain; 009 import aima.logic.fol.kb.data.CNF; 010 import aima.logic.fol.kb.data.Clause; 011 import aima.logic.fol.parsing.FOLParser; 012 import aima.logic.fol.parsing.ast.Sentence; 013 import junit.framework.TestCase; 014 015 /** 016 * @author Ciaran O'Reilly 017 * 018 */ 019 public class SubsumptionEliminationTest extends TestCase { 020 public void testFindSubsumedClauses() { 021 // Taken from AIMA pg 679 022 FOLDomain domain = new FOLDomain(); 023 domain.addPredicate("patrons"); 024 domain.addPredicate("hungry"); 025 domain.addPredicate("type"); 026 domain.addPredicate("fri_sat"); 027 domain.addPredicate("will_wait"); 028 domain.addConstant("Some"); 029 domain.addConstant("Full"); 030 domain.addConstant("French"); 031 domain.addConstant("Thai"); 032 domain.addConstant("Burger"); 033 FOLParser parser = new FOLParser(domain); 034 035 String c1 = "patrons(v,Some)"; 036 String c2 = "patrons(v,Full) AND (hungry(v) AND type(v,French))"; 037 String c3 = "patrons(v,Full) AND (hungry(v) AND (type(v,Thai) AND fri_sat(v)))"; 038 String c4 = "patrons(v,Full) AND (hungry(v) AND type(v,Burger))"; 039 String sh = "FORALL v (will_wait(v) <=> (" + c1 + " OR (" + c2 040 + " OR (" + c3 + " OR (" + c4 + ")))))"; 041 042 Sentence s = parser.parse(sh); 043 044 CNFConverter cnfConv = new CNFConverter(parser); 045 046 CNF cnf = cnfConv.convertToCNF(s); 047 048 // Contains 9 duplicates 049 assertEquals(40, cnf.getNumberOfClauses()); 050 051 Set<Clause> clauses = new HashSet<Clause>(cnf.getConjunctionOfClauses()); 052 053 // duplicates removed 054 assertEquals(31, clauses.size()); 055 056 clauses.removeAll(SubsumptionElimination.findSubsumedClauses(clauses)); 057 058 // subsumed clauses removed 059 assertEquals(8, clauses.size()); 060 061 // Ensure only the 8 correct/expected clauses remain 062 Clause cl1 = cnfConv 063 .convertToCNF( 064 parser 065 .parse("(NOT(will_wait(v)) OR (patrons(v,Full) OR patrons(v,Some)))")) 066 .getConjunctionOfClauses().get(0); 067 Clause cl2 = cnfConv 068 .convertToCNF( 069 parser 070 .parse("(NOT(will_wait(v)) OR (hungry(v) OR patrons(v,Some)))")) 071 .getConjunctionOfClauses().get(0); 072 Clause cl3 = cnfConv 073 .convertToCNF( 074 parser 075 .parse("(NOT(will_wait(v)) OR (patrons(v,Some) OR (type(v,Burger) OR (type(v,French) OR type(v,Thai)))))")) 076 .getConjunctionOfClauses().get(0); 077 Clause cl4 = cnfConv 078 .convertToCNF( 079 parser 080 .parse("(NOT(will_wait(v)) OR (fri_sat(v) OR (patrons(v,Some) OR (type(v,Burger) OR type(v,French)))))")) 081 .getConjunctionOfClauses().get(0); 082 Clause cl5 = cnfConv.convertToCNF( 083 parser.parse("(NOT(patrons(v,Some)) OR will_wait(v))")) 084 .getConjunctionOfClauses().get(0); 085 Clause cl6 = cnfConv 086 .convertToCNF( 087 parser 088 .parse("(NOT(hungry(v)) OR (NOT(patrons(v,Full)) OR (NOT(type(v,French)) OR will_wait(v))))")) 089 .getConjunctionOfClauses().get(0); 090 Clause cl7 = cnfConv 091 .convertToCNF( 092 parser 093 .parse("(NOT(fri_sat(v)) OR (NOT(hungry(v)) OR (NOT(patrons(v,Full)) OR (NOT(type(v,Thai)) OR will_wait(v)))))")) 094 .getConjunctionOfClauses().get(0); 095 Clause cl8 = cnfConv 096 .convertToCNF( 097 parser 098 .parse("(NOT(hungry(v)) OR (NOT(patrons(v,Full)) OR (NOT(type(v,Burger)) OR will_wait(v))))")) 099 .getConjunctionOfClauses().get(0); 100 101 assertTrue(clauses.contains(cl1)); 102 assertTrue(clauses.contains(cl2)); 103 assertTrue(clauses.contains(cl3)); 104 assertTrue(clauses.contains(cl4)); 105 assertTrue(clauses.contains(cl5)); 106 assertTrue(clauses.contains(cl6)); 107 assertTrue(clauses.contains(cl7)); 108 assertTrue(clauses.contains(cl8)); 109 } 110 }