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    }