Package aima.test.core.unit.logic.fol.kb.data

Source Code of aima.test.core.unit.logic.fol.kb.data.ClauseTest

package aima.test.core.unit.logic.fol.kb.data;

import java.util.ArrayList;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;

import aima.core.logic.fol.CNFConverter;
import aima.core.logic.fol.StandardizeApartIndexicalFactory;
import aima.core.logic.fol.domain.DomainFactory;
import aima.core.logic.fol.domain.FOLDomain;
import aima.core.logic.fol.kb.FOLKnowledgeBase;
import aima.core.logic.fol.kb.data.CNF;
import aima.core.logic.fol.kb.data.Clause;
import aima.core.logic.fol.kb.data.Literal;
import aima.core.logic.fol.parsing.FOLParser;
import aima.core.logic.fol.parsing.ast.AtomicSentence;
import aima.core.logic.fol.parsing.ast.Constant;
import aima.core.logic.fol.parsing.ast.Function;
import aima.core.logic.fol.parsing.ast.Predicate;
import aima.core.logic.fol.parsing.ast.Sentence;
import aima.core.logic.fol.parsing.ast.Term;
import aima.core.logic.fol.parsing.ast.Variable;

/**
* @author Ciaran O'Reilly
*
*/
public class ClauseTest {

  @Before
  public void setUp() {
    StandardizeApartIndexicalFactory.flush();
  }

  @Test
  public void testImmutable() {
    Clause c = new Clause();

    Assert.assertFalse(c.isImmutable());

    c.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));

    c.setImmutable();

    Assert.assertTrue(c.isImmutable());

    try {
      c.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));

      Assert.fail("Should have thrown an IllegalStateException");
    } catch (IllegalStateException ise) {
      // Ok, Expected
    }

    try {
      c.addPositiveLiteral(new Predicate("Pred3", new ArrayList<Term>()));

      Assert.fail("Should have thrown an IllegalStateException");
    } catch (IllegalStateException ise) {
      // Ok, Expected
    }
  }

  @Test
  public void testIsEmpty() {
    Clause c1 = new Clause();
    Assert.assertTrue(c1.isEmpty());

    c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertFalse(c1.isEmpty());

    Clause c2 = new Clause();
    Assert.assertTrue(c2.isEmpty());

    c2.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertFalse(c2.isEmpty());

    Clause c3 = new Clause();
    Assert.assertTrue(c3.isEmpty());

    c3.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c3.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    // Should be empty as they resolved with each other
    Assert.assertFalse(c3.isEmpty());

    c3.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c3.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertFalse(c3.isEmpty());
  }

  @Test
  public void testIsHornClause() {
    Clause c1 = new Clause();
    Assert.assertFalse(c1.isHornClause());

    c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertTrue(c1.isHornClause());

    c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertTrue(c1.isHornClause());

    c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
    Assert.assertTrue(c1.isHornClause());
    c1.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
    Assert.assertTrue(c1.isHornClause());

    c1.addPositiveLiteral(new Predicate("Pred5", new ArrayList<Term>()));
    Assert.assertFalse(c1.isHornClause());
  }

  @Test
  public void testIsDefiniteClause() {
    Clause c1 = new Clause();
    Assert.assertFalse(c1.isDefiniteClause());

    c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertFalse(c1.isDefiniteClause());

    c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertTrue(c1.isDefiniteClause());

    c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
    Assert.assertTrue(c1.isDefiniteClause());
    c1.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
    Assert.assertTrue(c1.isDefiniteClause());

    c1.addPositiveLiteral(new Predicate("Pred5", new ArrayList<Term>()));
    Assert.assertFalse(c1.isDefiniteClause());
  }

  @Test
  public void testIsUnitClause() {
    Clause c1 = new Clause();
    Assert.assertFalse(c1.isUnitClause());

    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertTrue(c1.isUnitClause());

    c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertFalse(c1.isUnitClause());

    c1 = new Clause();
    Assert.assertFalse(c1.isUnitClause());

    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertTrue(c1.isUnitClause());

    c1.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertFalse(c1.isUnitClause());

    c1 = new Clause();
    Assert.assertFalse(c1.isUnitClause());

    c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertTrue(c1.isUnitClause());

    c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertFalse(c1.isUnitClause());
  }

  @Test
  public void testIsImplicationDefiniteClause() {
    Clause c1 = new Clause();
    Assert.assertFalse(c1.isImplicationDefiniteClause());

    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertFalse(c1.isImplicationDefiniteClause());

    c1.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertTrue(c1.isImplicationDefiniteClause());
    c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
    Assert.assertTrue(c1.isImplicationDefiniteClause());

    c1.addPositiveLiteral(new Predicate("Pred4", new ArrayList<Term>()));
    Assert.assertFalse(c1.isImplicationDefiniteClause());
  }

  @Test
  public void testBinaryResolvents() {
    FOLDomain domain = new FOLDomain();
    domain.addPredicate("Pred1");
    domain.addPredicate("Pred2");
    domain.addPredicate("Pred3");
    domain.addPredicate("Pred4");

    Clause c1 = new Clause();

    // Ensure that resolving to self when empty returns an empty clause
    Assert.assertNotNull(c1.binaryResolvents(c1));
    Assert.assertEquals(1, c1.binaryResolvents(c1).size());
    Assert.assertTrue(c1.binaryResolvents(c1).iterator().next().isEmpty());

    // Check if resolve with self to an empty clause
    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertNotNull(c1.binaryResolvents(c1));
    Assert.assertEquals(1, c1.binaryResolvents(c1).size());
    // i.e. resolving a tautology with a tautology gives you
    // back a tautology.
    Assert.assertEquals("[~Pred1(), Pred1()]", c1.binaryResolvents(c1)
        .iterator().next().toString());

    // Check if try to resolve with self and no resolvents
    c1 = new Clause();
    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertEquals(0, c1.binaryResolvents(c1).size());

    c1 = new Clause();
    Clause c2 = new Clause();
    // Ensure that two empty clauses resolve to an empty clause
    Assert.assertNotNull(c1.binaryResolvents(c2));
    Assert.assertEquals(1, c1.binaryResolvents(c2).size());
    Assert.assertTrue(c1.binaryResolvents(c2).iterator().next().isEmpty());
    Assert.assertNotNull(c2.binaryResolvents(c1));
    Assert.assertEquals(1, c2.binaryResolvents(c1).size());
    Assert.assertTrue(c2.binaryResolvents(c1).iterator().next().isEmpty());

    // Enusre the two complementary clauses resolve
    // to the empty clause
    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c2.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    Assert.assertNotNull(c1.binaryResolvents(c2));
    Assert.assertEquals(1, c1.binaryResolvents(c2).size());
    Assert.assertTrue(c1.binaryResolvents(c2).iterator().next().isEmpty());
    Assert.assertNotNull(c2.binaryResolvents(c1));
    Assert.assertEquals(1, c2.binaryResolvents(c1).size());
    Assert.assertTrue(c2.binaryResolvents(c1).iterator().next().isEmpty());

    // Ensure that two clauses that have two complementaries
    // resolve with two resolvents
    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c2.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    c2.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertNotNull(c1.binaryResolvents(c2));
    Assert.assertEquals(2, c1.binaryResolvents(c2).size());
    Assert.assertNotNull(c2.binaryResolvents(c1));
    Assert.assertEquals(2, c2.binaryResolvents(c1).size());

    // Ensure two clauses that factor are not
    // considered resolved
    c1 = new Clause();
    c2 = new Clause();
    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
    c1.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
    c2.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    c2.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
    Assert.assertNotNull(c1.binaryResolvents(c2));
    Assert.assertEquals(0, c1.binaryResolvents(c2).size());
    Assert.assertNotNull(c2.binaryResolvents(c1));
    Assert.assertEquals(0, c2.binaryResolvents(c1).size());

    // Ensure the resolvent is a subset of the originals
    c1 = new Clause();
    c2 = new Clause();
    c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
    c1.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
    c2.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
    Assert.assertNotNull(c1.binaryResolvents(c2));
    Assert.assertNotNull(c2.binaryResolvents(c1));
    Assert.assertEquals(1, c1.binaryResolvents(c2).iterator().next()
        .getNumberPositiveLiterals());
    Assert.assertEquals(1, c1.binaryResolvents(c2).iterator().next()
        .getNumberNegativeLiterals());
    Assert.assertEquals(1, c2.binaryResolvents(c1).iterator().next()
        .getNumberPositiveLiterals());
    Assert.assertEquals(1, c2.binaryResolvents(c1).iterator().next()
        .getNumberNegativeLiterals());
  }

  @Test
  public void testBinaryResolventsOrderDoesNotMatter() {
    // This is a regression test, to ensure
    // the ordering of resolvents does not matter.
    // If the order ends up mattering, then likely
    // a problem was introduced in the Clause class
    // unifier, or related class.

    // Set up the initial set of clauses based on the
    // loves animal domain as it contains functions
    // new clauses will always be created (i.e. is an
    // infinite universe of discourse).
    FOLKnowledgeBase kb = new FOLKnowledgeBase(
        DomainFactory.lovesAnimalDomain());

    kb.tell("FORALL x (FORALL y (Animal(y) => Loves(x, y)) => EXISTS y Loves(y, x))");
    kb.tell("FORALL x (EXISTS y (Animal(y) AND Kills(x, y)) => FORALL z NOT(Loves(z, x)))");
    kb.tell("FORALL x (Animal(x) => Loves(Jack, x))");
    kb.tell("(Kills(Jack, Tuna) OR Kills(Curiosity, Tuna))");
    kb.tell("Cat(Tuna)");
    kb.tell("FORALL x (Cat(x) => Animal(x))");

    Set<Clause> clauses = new LinkedHashSet<Clause>();
    clauses.addAll(kb.getAllClauses());

    Set<Clause> newClauses = new LinkedHashSet<Clause>();
    long maxRunTime = 30 * 1000; // 30 seconds
    long finishTime = System.currentTimeMillis() + maxRunTime;
    do {
      clauses.addAll(newClauses);
      newClauses.clear();
      Clause[] clausesA = new Clause[clauses.size()];
      clauses.toArray(clausesA);
      for (int i = 0; i < clausesA.length; i++) {
        Clause cI = clausesA[i];
        for (int j = 0; j < clausesA.length; j++) {
          Clause cJ = clausesA[j];

          newClauses.addAll(cI.getFactors());
          newClauses.addAll(cJ.getFactors());

          Set<Clause> cIresolvents = cI.binaryResolvents(cJ);
          Set<Clause> cJresolvents = cJ.binaryResolvents(cI);
          if (!cIresolvents.equals(cJresolvents)) {
            System.err.println("cI=" + cI);
            System.err.println("cJ=" + cJ);
            System.err.println("cIR=" + cIresolvents);
            System.err.println("cJR=" + cJresolvents);
            Assert.fail("Ordering of binary resolvents has become important, which should not be the case");
          }

          for (Clause r : cIresolvents) {
            newClauses.addAll(r.getFactors());
          }

          if (System.currentTimeMillis() > finishTime) {
            break;
          }
        }
        if (System.currentTimeMillis() > finishTime) {
          break;
        }
      }
    } while (System.currentTimeMillis() < finishTime);
  }

  @Test
  public void testEqualityBinaryResolvents() {
    FOLDomain domain = new FOLDomain();
    domain.addConstant("A");
    domain.addConstant("B");

    FOLParser parser = new FOLParser(domain);

    // B = A
    Clause c1 = new Clause();
    c1.addPositiveLiteral((AtomicSentence) parser.parse("B = A"));

    Clause c2 = new Clause();
    c2.addNegativeLiteral((AtomicSentence) parser.parse("B = A"));
    c2.addPositiveLiteral((AtomicSentence) parser.parse("B = A"));

    Set<Clause> resolvents = c1.binaryResolvents(c2);

    Assert.assertEquals(1, resolvents.size());
    Assert.assertEquals("[[B = A]]", resolvents.toString());
  }

  @Test
  public void testHashCode() {
    Term cons1 = new Constant("C1");
    Term cons2 = new Constant("C2");
    Term var1 = new Variable("v1");
    List<Term> pts1 = new ArrayList<Term>();
    List<Term> pts2 = new ArrayList<Term>();
    pts1.add(cons1);
    pts1.add(cons2);
    pts1.add(var1);
    pts2.add(cons2);
    pts2.add(cons1);
    pts2.add(var1);

    Clause c1 = new Clause();
    Clause c2 = new Clause();
    Assert.assertEquals(c1.hashCode(), c2.hashCode());

    c1.addNegativeLiteral(new Predicate("Pred1", pts1));
    Assert.assertNotSame(c1.hashCode(), c2.hashCode());
    c2.addNegativeLiteral(new Predicate("Pred1", pts1));
    Assert.assertEquals(c1.hashCode(), c2.hashCode());

    c1.addPositiveLiteral(new Predicate("Pred1", pts1));
    Assert.assertNotSame(c1.hashCode(), c2.hashCode());
    c2.addPositiveLiteral(new Predicate("Pred1", pts1));
    Assert.assertEquals(c1.hashCode(), c2.hashCode());
  }

  @Test
  public void testSimpleEquals() {
    Term cons1 = new Constant("C1");
    Term cons2 = new Constant("C2");
    Term var1 = new Variable("v1");
    List<Term> pts1 = new ArrayList<Term>();
    List<Term> pts2 = new ArrayList<Term>();
    pts1.add(cons1);
    pts1.add(cons2);
    pts1.add(var1);
    pts2.add(cons2);
    pts2.add(cons1);
    pts2.add(var1);

    Clause c1 = new Clause();
    Clause c2 = new Clause();
    Assert.assertTrue(c1.equals(c1));
    Assert.assertTrue(c2.equals(c2));
    Assert.assertTrue(c1.equals(c2));
    Assert.assertTrue(c2.equals(c1));

    // Check negatives
    c1.addNegativeLiteral(new Predicate("Pred1", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addNegativeLiteral(new Predicate("Pred1", pts1));
    Assert.assertTrue(c1.equals(c2));
    Assert.assertTrue(c2.equals(c1));

    c1.addNegativeLiteral(new Predicate("Pred2", pts2));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addNegativeLiteral(new Predicate("Pred2", pts2));
    Assert.assertTrue(c1.equals(c2));
    Assert.assertTrue(c2.equals(c1));
    // Check same but added in different order
    c1.addNegativeLiteral(new Predicate("Pred3", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c1.addNegativeLiteral(new Predicate("Pred4", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addNegativeLiteral(new Predicate("Pred4", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addNegativeLiteral(new Predicate("Pred3", pts1));
    Assert.assertTrue(c1.equals(c2));
    Assert.assertTrue(c2.equals(c1));

    // Check positives
    c1.addPositiveLiteral(new Predicate("Pred1", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addPositiveLiteral(new Predicate("Pred1", pts1));
    Assert.assertTrue(c1.equals(c2));
    Assert.assertTrue(c2.equals(c1));

    c1.addPositiveLiteral(new Predicate("Pred2", pts2));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addPositiveLiteral(new Predicate("Pred2", pts2));
    Assert.assertTrue(c1.equals(c2));
    Assert.assertTrue(c2.equals(c1));
    // Check same but added in different order
    c1.addPositiveLiteral(new Predicate("Pred3", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c1.addPositiveLiteral(new Predicate("Pred4", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addPositiveLiteral(new Predicate("Pred4", pts1));
    Assert.assertFalse(c1.equals(c2));
    Assert.assertFalse(c2.equals(c1));
    c2.addPositiveLiteral(new Predicate("Pred3", pts1));
    Assert.assertTrue(c1.equals(c2));
    Assert.assertTrue(c2.equals(c1));
  }

  @Test
  public void testComplexEquals() {
    FOLDomain domain = new FOLDomain();
    domain.addConstant("A");
    domain.addConstant("B");
    domain.addConstant("C");
    domain.addConstant("D");
    domain.addPredicate("P");
    domain.addPredicate("Animal");
    domain.addPredicate("Kills");
    domain.addFunction("F");
    domain.addFunction("SF0");

    FOLParser parser = new FOLParser(domain);

    CNFConverter cnfConverter = new CNFConverter(parser);
    Sentence s1 = parser.parse("((x1 = y1 AND y1 = z1) => x1 = z1)");
    Sentence s2 = parser.parse("((x2 = y2 AND F(y2) = z2) => F(x2) = z2)");
    CNF cnf1 = cnfConverter.convertToCNF(s1);
    CNF cnf2 = cnfConverter.convertToCNF(s2);

    Clause c1 = cnf1.getConjunctionOfClauses().get(0);
    Clause c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertFalse(c1.equals(c2));

    s1 = parser.parse("((x1 = y1 AND y1 = z1) => x1 = z1)");
    s2 = parser.parse("((x2 = y2 AND y2 = z2) => x2 = z2)");
    cnf1 = cnfConverter.convertToCNF(s1);
    cnf2 = cnfConverter.convertToCNF(s2);

    c1 = cnf1.getConjunctionOfClauses().get(0);
    c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertTrue(c1.equals(c2));

    s1 = parser.parse("((x1 = y1 AND y1 = z1) => x1 = z1)");
    s2 = parser.parse("((y2 = z2 AND x2 = y2) => x2 = z2)");
    cnf1 = cnfConverter.convertToCNF(s1);
    cnf2 = cnfConverter.convertToCNF(s2);

    c1 = cnf1.getConjunctionOfClauses().get(0);
    c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertTrue(c1.equals(c2));

    s1 = parser.parse("(((x1 = y1 AND y1 = z1) AND z1 = r1) => x1 = r1)");
    s2 = parser.parse("(((x2 = y2 AND y2 = z2) AND z2 = r2) => x2 = r2)");
    cnf1 = cnfConverter.convertToCNF(s1);
    cnf2 = cnfConverter.convertToCNF(s2);

    c1 = cnf1.getConjunctionOfClauses().get(0);
    c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertTrue(c1.equals(c2));

    s1 = parser.parse("(((x1 = y1 AND y1 = z1) AND z1 = r1) => x1 = r1)");
    s2 = parser.parse("(((z2 = r2 AND y2 = z2) AND x2 = y2) => x2 = r2)");
    cnf1 = cnfConverter.convertToCNF(s1);
    cnf2 = cnfConverter.convertToCNF(s2);

    c1 = cnf1.getConjunctionOfClauses().get(0);
    c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertTrue(c1.equals(c2));

    s1 = parser.parse("(((x1 = y1 AND y1 = z1) AND z1 = r1) => x1 = r1)");
    s2 = parser.parse("(((x2 = y2 AND y2 = z2) AND z2 = y2) => x2 = r2)");
    cnf1 = cnfConverter.convertToCNF(s1);
    cnf2 = cnfConverter.convertToCNF(s2);

    c1 = cnf1.getConjunctionOfClauses().get(0);
    c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertFalse(c1.equals(c2));

    s1 = parser
        .parse("(((((x1 = y1 AND y1 = z1) AND z1 = r1) AND r1 = q1) AND q1 = s1) => x1 = r1)");
    s2 = parser
        .parse("(((((x2 = y2 AND y2 = z2) AND z2 = r2) AND r2 = q2) AND q2 = s2) => x2 = r2)");
    cnf1 = cnfConverter.convertToCNF(s1);
    cnf2 = cnfConverter.convertToCNF(s2);

    c1 = cnf1.getConjunctionOfClauses().get(0);
    c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertTrue(c1.equals(c2));

    s1 = parser
        .parse("((((NOT(Animal(c1920)) OR NOT(Animal(c1921))) OR NOT(Kills(c1922,c1920))) OR NOT(Kills(c1919,c1921))) OR NOT(Kills(SF0(c1922),SF0(c1919))))");
    s2 = parser
        .parse("((((NOT(Animal(c1929)) OR NOT(Animal(c1928))) OR NOT(Kills(c1927,c1929))) OR NOT(Kills(c1930,c1928))) OR NOT(Kills(SF0(c1930),SF0(c1927))))");
    cnf1 = cnfConverter.convertToCNF(s1);
    cnf2 = cnfConverter.convertToCNF(s2);

    c1 = cnf1.getConjunctionOfClauses().get(0);
    c2 = cnf2.getConjunctionOfClauses().get(0);

    Assert.assertTrue(c1.equals(c2));
  }

  @Test
  public void testNonTrivialFactors() {
    FOLDomain domain = new FOLDomain();
    domain.addConstant("A");
    domain.addConstant("B");
    domain.addFunction("F");
    domain.addFunction("G");
    domain.addFunction("H");
    domain.addPredicate("P");
    domain.addPredicate("Q");

    FOLParser parser = new FOLParser(domain);

    // p(x,y), q(a,b), p(b,a), q(y,x)
    Clause c = new Clause();
    c.addPositiveLiteral((Predicate) parser.parse("P(x,y)"));
    c.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
    c.addNegativeLiteral((Predicate) parser.parse("P(B,A)"));
    c.addPositiveLiteral((Predicate) parser.parse("Q(y,x)"));

    Assert.assertEquals("[[~P(B,A), P(B,A), Q(A,B)]]", c
        .getNonTrivialFactors().toString());

    // p(x,y), q(a,b), p(b,a), q(y,x)
    c = new Clause();
    c.addPositiveLiteral((Predicate) parser.parse("P(x,y)"));
    c.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
    c.addNegativeLiteral((Predicate) parser.parse("P(B,A)"));
    c.addNegativeLiteral((Predicate) parser.parse("Q(y,x)"));

    Assert.assertEquals("[]", c.getNonTrivialFactors().toString());

    // p(x,f(y)), p(g(u),x), p(f(y),u)
    c = new Clause();
    c.addPositiveLiteral((Predicate) parser.parse("P(x,F(y))"));
    c.addPositiveLiteral((Predicate) parser.parse("P(G(u),x)"));
    c.addPositiveLiteral((Predicate) parser.parse("P(F(y),u)"));

    // Should be: [{P(F(c#),F(c#)),P(G(F(c#)),F(c#))}]
    c = c.getNonTrivialFactors().iterator().next();
    Literal p = c.getPositiveLiterals().get(0);
    Assert.assertEquals("P", p.getAtomicSentence().getSymbolicName());
    Function f = (Function) p.getAtomicSentence().getArgs().get(0);
    Assert.assertEquals("F", f.getFunctionName());
    Variable v = (Variable) f.getTerms().get(0);
    f = (Function) p.getAtomicSentence().getArgs().get(1);
    Assert.assertEquals("F", f.getFunctionName());
    Assert.assertEquals(v, f.getTerms().get(0));

    //
    p = c.getPositiveLiterals().get(1);
    f = (Function) p.getAtomicSentence().getArgs().get(0);
    Assert.assertEquals("G", f.getFunctionName());
    f = (Function) f.getTerms().get(0);
    Assert.assertEquals("F", f.getFunctionName());
    Assert.assertEquals(v, f.getTerms().get(0));
    f = (Function) p.getAtomicSentence().getArgs().get(1);
    Assert.assertEquals("F", f.getFunctionName());
    Assert.assertEquals(v, f.getTerms().get(0));

    // p(g(x)), q(x), p(f(a)), p(x), p(g(f(x))), q(f(a))
    c = new Clause();
    c.addPositiveLiteral((Predicate) parser.parse("P(G(x))"));
    c.addPositiveLiteral((Predicate) parser.parse("Q(x)"));
    c.addPositiveLiteral((Predicate) parser.parse("P(F(A))"));
    c.addPositiveLiteral((Predicate) parser.parse("P(x)"));
    c.addPositiveLiteral((Predicate) parser.parse("P(G(F(x)))"));
    c.addPositiveLiteral((Predicate) parser.parse("Q(F(A))"));

    Assert.assertEquals("[[P(F(A)), P(G(F(F(A)))), P(G(F(A))), Q(F(A))]]",
        c.getNonTrivialFactors().toString());
  }

  // Note: Tests derived from:
  // http://logic.stanford.edu/classes/cs157/2008/notes/chap09.pdf
  // page 16.
  @Test
  public void testIsTautology() {
    FOLDomain domain = new FOLDomain();
    domain.addConstant("A");
    domain.addPredicate("P");
    domain.addPredicate("Q");
    domain.addPredicate("R");
    domain.addFunction("F");

    FOLParser parser = new FOLParser(domain);

    // {p(f(a)),~p(f(a))}
    Clause c = new Clause();
    c.addPositiveLiteral((Predicate) parser.parse("P(F(A))"));
    Assert.assertFalse(c.isTautology());
    c.addNegativeLiteral((Predicate) parser.parse("P(F(A))"));
    Assert.assertTrue(c.isTautology());

    // {p(x),q(y),~q(y),r(z)}
    c = new Clause();
    c.addPositiveLiteral((Predicate) parser.parse("P(x)"));
    Assert.assertFalse(c.isTautology());
    c.addPositiveLiteral((Predicate) parser.parse("Q(y)"));
    Assert.assertFalse(c.isTautology());
    c.addNegativeLiteral((Predicate) parser.parse("Q(y)"));
    Assert.assertTrue(c.isTautology());
    c.addPositiveLiteral((Predicate) parser.parse("R(z)"));
    Assert.assertTrue(c.isTautology());

    // {~p(a),p(x)}
    c = new Clause();
    c.addNegativeLiteral((Predicate) parser.parse("P(A)"));
    Assert.assertFalse(c.isTautology());
    c.addPositiveLiteral((Predicate) parser.parse("P(x)"));
    Assert.assertFalse(c.isTautology());
  }

  // Note: Tests derived from:
  // http://logic.stanford.edu/classes/cs157/2008/lectures/lecture12.pdf
  // slides 17 and 18.
  @Test
  public void testSubsumes() {
    FOLDomain domain = new FOLDomain();
    domain.addConstant("A");
    domain.addConstant("B");
    domain.addConstant("C");
    domain.addConstant("D");
    domain.addConstant("E");
    domain.addConstant("F");
    domain.addConstant("G");
    domain.addConstant("H");
    domain.addConstant("I");
    domain.addConstant("J");
    domain.addPredicate("P");
    domain.addPredicate("Q");

    FOLParser parser = new FOLParser(domain);

    // Example
    // {~p(a,b),q(c)}
    Clause psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(x,y)}
    Clause phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(x,y)"));

    Assert.assertTrue(phi.subsumes(psi));
    // Non-Example
    // {~p(x,b),q(x)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(x,B)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(x)"));
    // {~p(a,y)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,y)"));
    // Reason for Non-Example:
    // {p(b,b)}
    // {~q(b)}
    Assert.assertFalse(phi.subsumes(psi));

    //
    // Additional Examples

    // Non-Example
    // {~p(x,b),q(z)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(x,B)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(z)"));
    // {~p(a,y)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,y)"));

    Assert.assertFalse(phi.subsumes(psi));

    // Example
    // {~p(a,b),~p(w,z),q(c)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(w,z)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(x,y),~p(a,b)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(x,y)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));

    Assert.assertTrue(phi.subsumes(psi));

    // Non-Example
    // {~p(v,b),~p(w,z),q(c)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(v,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(w,z)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(x,y),~p(a,b)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(x,y)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));

    Assert.assertFalse(phi.subsumes(psi));

    // Example
    // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(i,j)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));

    Assert.assertTrue(phi.subsumes(psi));

    // Example
    // {~p(a,b),~p(c,d),~p(e,f),q(c)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(e,f),~p(a,b),~p(c,d)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));

    Assert.assertTrue(phi.subsumes(psi));

    // Example
    // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(i,j),~p(c,d)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));

    Assert.assertTrue(phi.subsumes(psi));

    // Non-Example
    // {~p(a,b),~p(x,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(x,D)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(i,j),~p(c,d)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));

    Assert.assertFalse(phi.subsumes(psi));

    // Example
    // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
    // {~p(i,j),~p(a,x)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,x)"));

    Assert.assertTrue(phi.subsumes(psi));

    // Example
    // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(a,b),q(c,d),q(e,f)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C,D)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(E,F)"));
    // {~p(i,j),~p(a,b),q(e,f),q(a,b)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    phi.addPositiveLiteral((Predicate) parser.parse("Q(E,F)"));
    phi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));

    Assert.assertTrue(phi.subsumes(psi));

    // Non-Example
    // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(a,b),q(c,d),q(e,f)}
    psi = new Clause();
    psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
    psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(C,D)"));
    psi.addPositiveLiteral((Predicate) parser.parse("Q(E,F)"));
    // {~p(i,j),~p(a,b),q(e,f),q(a,b)}
    phi = new Clause();
    phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
    phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
    phi.addPositiveLiteral((Predicate) parser.parse("Q(E,A)"));
    phi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));

    Assert.assertFalse(phi.subsumes(psi));
  }
}
TOP

Related Classes of aima.test.core.unit.logic.fol.kb.data.ClauseTest

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.