PageRenderTime 48ms CodeModel.GetById 19ms RepoModel.GetById 0ms app.codeStats 0ms

/aima-core/src/test/java/aima/test/core/unit/logic/fol/kb/data/ClauseTest.java

http://aima-java.googlecode.com/
Java | 891 lines | 655 code | 146 blank | 90 comment | 7 complexity | 145b70147ed77c8b80f47aaeb7782f27 MD5 | raw file
Possible License(s): GPL-3.0, Apache-2.0
  1. package aima.test.core.unit.logic.fol.kb.data;
  2. import java.util.ArrayList;
  3. import java.util.LinkedHashSet;
  4. import java.util.List;
  5. import java.util.Set;
  6. import org.junit.Assert;
  7. import org.junit.Before;
  8. import org.junit.Test;
  9. import aima.core.logic.fol.CNFConverter;
  10. import aima.core.logic.fol.StandardizeApartIndexicalFactory;
  11. import aima.core.logic.fol.domain.DomainFactory;
  12. import aima.core.logic.fol.domain.FOLDomain;
  13. import aima.core.logic.fol.kb.FOLKnowledgeBase;
  14. import aima.core.logic.fol.kb.data.CNF;
  15. import aima.core.logic.fol.kb.data.Clause;
  16. import aima.core.logic.fol.kb.data.Literal;
  17. import aima.core.logic.fol.parsing.FOLParser;
  18. import aima.core.logic.fol.parsing.ast.AtomicSentence;
  19. import aima.core.logic.fol.parsing.ast.Constant;
  20. import aima.core.logic.fol.parsing.ast.Function;
  21. import aima.core.logic.fol.parsing.ast.Predicate;
  22. import aima.core.logic.fol.parsing.ast.Sentence;
  23. import aima.core.logic.fol.parsing.ast.Term;
  24. import aima.core.logic.fol.parsing.ast.Variable;
  25. /**
  26. * @author Ciaran O'Reilly
  27. *
  28. */
  29. public class ClauseTest {
  30. @Before
  31. public void setUp() {
  32. StandardizeApartIndexicalFactory.flush();
  33. }
  34. @Test
  35. public void testImmutable() {
  36. Clause c = new Clause();
  37. Assert.assertFalse(c.isImmutable());
  38. c.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  39. c.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  40. c.setImmutable();
  41. Assert.assertTrue(c.isImmutable());
  42. try {
  43. c.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
  44. Assert.fail("Should have thrown an IllegalStateException");
  45. } catch (IllegalStateException ise) {
  46. // Ok, Expected
  47. }
  48. try {
  49. c.addPositiveLiteral(new Predicate("Pred3", new ArrayList<Term>()));
  50. Assert.fail("Should have thrown an IllegalStateException");
  51. } catch (IllegalStateException ise) {
  52. // Ok, Expected
  53. }
  54. }
  55. @Test
  56. public void testIsEmpty() {
  57. Clause c1 = new Clause();
  58. Assert.assertTrue(c1.isEmpty());
  59. c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  60. Assert.assertFalse(c1.isEmpty());
  61. Clause c2 = new Clause();
  62. Assert.assertTrue(c2.isEmpty());
  63. c2.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  64. Assert.assertFalse(c2.isEmpty());
  65. Clause c3 = new Clause();
  66. Assert.assertTrue(c3.isEmpty());
  67. c3.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  68. c3.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  69. // Should be empty as they resolved with each other
  70. Assert.assertFalse(c3.isEmpty());
  71. c3.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  72. c3.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  73. Assert.assertFalse(c3.isEmpty());
  74. }
  75. @Test
  76. public void testIsHornClause() {
  77. Clause c1 = new Clause();
  78. Assert.assertFalse(c1.isHornClause());
  79. c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  80. Assert.assertTrue(c1.isHornClause());
  81. c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  82. Assert.assertTrue(c1.isHornClause());
  83. c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
  84. Assert.assertTrue(c1.isHornClause());
  85. c1.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
  86. Assert.assertTrue(c1.isHornClause());
  87. c1.addPositiveLiteral(new Predicate("Pred5", new ArrayList<Term>()));
  88. Assert.assertFalse(c1.isHornClause());
  89. }
  90. @Test
  91. public void testIsDefiniteClause() {
  92. Clause c1 = new Clause();
  93. Assert.assertFalse(c1.isDefiniteClause());
  94. c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  95. Assert.assertFalse(c1.isDefiniteClause());
  96. c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  97. Assert.assertTrue(c1.isDefiniteClause());
  98. c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
  99. Assert.assertTrue(c1.isDefiniteClause());
  100. c1.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
  101. Assert.assertTrue(c1.isDefiniteClause());
  102. c1.addPositiveLiteral(new Predicate("Pred5", new ArrayList<Term>()));
  103. Assert.assertFalse(c1.isDefiniteClause());
  104. }
  105. @Test
  106. public void testIsUnitClause() {
  107. Clause c1 = new Clause();
  108. Assert.assertFalse(c1.isUnitClause());
  109. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  110. Assert.assertTrue(c1.isUnitClause());
  111. c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  112. Assert.assertFalse(c1.isUnitClause());
  113. c1 = new Clause();
  114. Assert.assertFalse(c1.isUnitClause());
  115. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  116. Assert.assertTrue(c1.isUnitClause());
  117. c1.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  118. Assert.assertFalse(c1.isUnitClause());
  119. c1 = new Clause();
  120. Assert.assertFalse(c1.isUnitClause());
  121. c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  122. Assert.assertTrue(c1.isUnitClause());
  123. c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  124. Assert.assertFalse(c1.isUnitClause());
  125. }
  126. @Test
  127. public void testIsImplicationDefiniteClause() {
  128. Clause c1 = new Clause();
  129. Assert.assertFalse(c1.isImplicationDefiniteClause());
  130. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  131. Assert.assertFalse(c1.isImplicationDefiniteClause());
  132. c1.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  133. Assert.assertTrue(c1.isImplicationDefiniteClause());
  134. c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
  135. Assert.assertTrue(c1.isImplicationDefiniteClause());
  136. c1.addPositiveLiteral(new Predicate("Pred4", new ArrayList<Term>()));
  137. Assert.assertFalse(c1.isImplicationDefiniteClause());
  138. }
  139. @Test
  140. public void testBinaryResolvents() {
  141. FOLDomain domain = new FOLDomain();
  142. domain.addPredicate("Pred1");
  143. domain.addPredicate("Pred2");
  144. domain.addPredicate("Pred3");
  145. domain.addPredicate("Pred4");
  146. Clause c1 = new Clause();
  147. // Ensure that resolving to self when empty returns an empty clause
  148. Assert.assertNotNull(c1.binaryResolvents(c1));
  149. Assert.assertEquals(1, c1.binaryResolvents(c1).size());
  150. Assert.assertTrue(c1.binaryResolvents(c1).iterator().next().isEmpty());
  151. // Check if resolve with self to an empty clause
  152. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  153. c1.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  154. Assert.assertNotNull(c1.binaryResolvents(c1));
  155. Assert.assertEquals(1, c1.binaryResolvents(c1).size());
  156. // i.e. resolving a tautology with a tautology gives you
  157. // back a tautology.
  158. Assert.assertEquals("[~Pred1(), Pred1()]", c1.binaryResolvents(c1)
  159. .iterator().next().toString());
  160. // Check if try to resolve with self and no resolvents
  161. c1 = new Clause();
  162. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  163. Assert.assertEquals(0, c1.binaryResolvents(c1).size());
  164. c1 = new Clause();
  165. Clause c2 = new Clause();
  166. // Ensure that two empty clauses resolve to an empty clause
  167. Assert.assertNotNull(c1.binaryResolvents(c2));
  168. Assert.assertEquals(1, c1.binaryResolvents(c2).size());
  169. Assert.assertTrue(c1.binaryResolvents(c2).iterator().next().isEmpty());
  170. Assert.assertNotNull(c2.binaryResolvents(c1));
  171. Assert.assertEquals(1, c2.binaryResolvents(c1).size());
  172. Assert.assertTrue(c2.binaryResolvents(c1).iterator().next().isEmpty());
  173. // Enusre the two complementary clauses resolve
  174. // to the empty clause
  175. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  176. c2.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  177. Assert.assertNotNull(c1.binaryResolvents(c2));
  178. Assert.assertEquals(1, c1.binaryResolvents(c2).size());
  179. Assert.assertTrue(c1.binaryResolvents(c2).iterator().next().isEmpty());
  180. Assert.assertNotNull(c2.binaryResolvents(c1));
  181. Assert.assertEquals(1, c2.binaryResolvents(c1).size());
  182. Assert.assertTrue(c2.binaryResolvents(c1).iterator().next().isEmpty());
  183. // Ensure that two clauses that have two complementaries
  184. // resolve with two resolvents
  185. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  186. c2.addNegativeLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  187. c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  188. c2.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  189. Assert.assertNotNull(c1.binaryResolvents(c2));
  190. Assert.assertEquals(2, c1.binaryResolvents(c2).size());
  191. Assert.assertNotNull(c2.binaryResolvents(c1));
  192. Assert.assertEquals(2, c2.binaryResolvents(c1).size());
  193. // Ensure two clauses that factor are not
  194. // considered resolved
  195. c1 = new Clause();
  196. c2 = new Clause();
  197. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  198. c1.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  199. c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
  200. c1.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
  201. c2.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  202. c2.addNegativeLiteral(new Predicate("Pred4", new ArrayList<Term>()));
  203. Assert.assertNotNull(c1.binaryResolvents(c2));
  204. Assert.assertEquals(0, c1.binaryResolvents(c2).size());
  205. Assert.assertNotNull(c2.binaryResolvents(c1));
  206. Assert.assertEquals(0, c2.binaryResolvents(c1).size());
  207. // Ensure the resolvent is a subset of the originals
  208. c1 = new Clause();
  209. c2 = new Clause();
  210. c1.addPositiveLiteral(new Predicate("Pred1", new ArrayList<Term>()));
  211. c1.addNegativeLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  212. c1.addNegativeLiteral(new Predicate("Pred3", new ArrayList<Term>()));
  213. c2.addPositiveLiteral(new Predicate("Pred2", new ArrayList<Term>()));
  214. Assert.assertNotNull(c1.binaryResolvents(c2));
  215. Assert.assertNotNull(c2.binaryResolvents(c1));
  216. Assert.assertEquals(1, c1.binaryResolvents(c2).iterator().next()
  217. .getNumberPositiveLiterals());
  218. Assert.assertEquals(1, c1.binaryResolvents(c2).iterator().next()
  219. .getNumberNegativeLiterals());
  220. Assert.assertEquals(1, c2.binaryResolvents(c1).iterator().next()
  221. .getNumberPositiveLiterals());
  222. Assert.assertEquals(1, c2.binaryResolvents(c1).iterator().next()
  223. .getNumberNegativeLiterals());
  224. }
  225. @Test
  226. public void testBinaryResolventsOrderDoesNotMatter() {
  227. // This is a regression test, to ensure
  228. // the ordering of resolvents does not matter.
  229. // If the order ends up mattering, then likely
  230. // a problem was introduced in the Clause class
  231. // unifier, or related class.
  232. // Set up the initial set of clauses based on the
  233. // loves animal domain as it contains functions
  234. // new clauses will always be created (i.e. is an
  235. // infinite universe of discourse).
  236. FOLKnowledgeBase kb = new FOLKnowledgeBase(
  237. DomainFactory.lovesAnimalDomain());
  238. kb.tell("FORALL x (FORALL y (Animal(y) => Loves(x, y)) => EXISTS y Loves(y, x))");
  239. kb.tell("FORALL x (EXISTS y (Animal(y) AND Kills(x, y)) => FORALL z NOT(Loves(z, x)))");
  240. kb.tell("FORALL x (Animal(x) => Loves(Jack, x))");
  241. kb.tell("(Kills(Jack, Tuna) OR Kills(Curiosity, Tuna))");
  242. kb.tell("Cat(Tuna)");
  243. kb.tell("FORALL x (Cat(x) => Animal(x))");
  244. Set<Clause> clauses = new LinkedHashSet<Clause>();
  245. clauses.addAll(kb.getAllClauses());
  246. Set<Clause> newClauses = new LinkedHashSet<Clause>();
  247. long maxRunTime = 30 * 1000; // 30 seconds
  248. long finishTime = System.currentTimeMillis() + maxRunTime;
  249. do {
  250. clauses.addAll(newClauses);
  251. newClauses.clear();
  252. Clause[] clausesA = new Clause[clauses.size()];
  253. clauses.toArray(clausesA);
  254. for (int i = 0; i < clausesA.length; i++) {
  255. Clause cI = clausesA[i];
  256. for (int j = 0; j < clausesA.length; j++) {
  257. Clause cJ = clausesA[j];
  258. newClauses.addAll(cI.getFactors());
  259. newClauses.addAll(cJ.getFactors());
  260. Set<Clause> cIresolvents = cI.binaryResolvents(cJ);
  261. Set<Clause> cJresolvents = cJ.binaryResolvents(cI);
  262. if (!cIresolvents.equals(cJresolvents)) {
  263. System.err.println("cI=" + cI);
  264. System.err.println("cJ=" + cJ);
  265. System.err.println("cIR=" + cIresolvents);
  266. System.err.println("cJR=" + cJresolvents);
  267. Assert.fail("Ordering of binary resolvents has become important, which should not be the case");
  268. }
  269. for (Clause r : cIresolvents) {
  270. newClauses.addAll(r.getFactors());
  271. }
  272. if (System.currentTimeMillis() > finishTime) {
  273. break;
  274. }
  275. }
  276. if (System.currentTimeMillis() > finishTime) {
  277. break;
  278. }
  279. }
  280. } while (System.currentTimeMillis() < finishTime);
  281. }
  282. @Test
  283. public void testEqualityBinaryResolvents() {
  284. FOLDomain domain = new FOLDomain();
  285. domain.addConstant("A");
  286. domain.addConstant("B");
  287. FOLParser parser = new FOLParser(domain);
  288. // B = A
  289. Clause c1 = new Clause();
  290. c1.addPositiveLiteral((AtomicSentence) parser.parse("B = A"));
  291. Clause c2 = new Clause();
  292. c2.addNegativeLiteral((AtomicSentence) parser.parse("B = A"));
  293. c2.addPositiveLiteral((AtomicSentence) parser.parse("B = A"));
  294. Set<Clause> resolvents = c1.binaryResolvents(c2);
  295. Assert.assertEquals(1, resolvents.size());
  296. Assert.assertEquals("[[B = A]]", resolvents.toString());
  297. }
  298. @Test
  299. public void testHashCode() {
  300. Term cons1 = new Constant("C1");
  301. Term cons2 = new Constant("C2");
  302. Term var1 = new Variable("v1");
  303. List<Term> pts1 = new ArrayList<Term>();
  304. List<Term> pts2 = new ArrayList<Term>();
  305. pts1.add(cons1);
  306. pts1.add(cons2);
  307. pts1.add(var1);
  308. pts2.add(cons2);
  309. pts2.add(cons1);
  310. pts2.add(var1);
  311. Clause c1 = new Clause();
  312. Clause c2 = new Clause();
  313. Assert.assertEquals(c1.hashCode(), c2.hashCode());
  314. c1.addNegativeLiteral(new Predicate("Pred1", pts1));
  315. Assert.assertNotSame(c1.hashCode(), c2.hashCode());
  316. c2.addNegativeLiteral(new Predicate("Pred1", pts1));
  317. Assert.assertEquals(c1.hashCode(), c2.hashCode());
  318. c1.addPositiveLiteral(new Predicate("Pred1", pts1));
  319. Assert.assertNotSame(c1.hashCode(), c2.hashCode());
  320. c2.addPositiveLiteral(new Predicate("Pred1", pts1));
  321. Assert.assertEquals(c1.hashCode(), c2.hashCode());
  322. }
  323. @Test
  324. public void testSimpleEquals() {
  325. Term cons1 = new Constant("C1");
  326. Term cons2 = new Constant("C2");
  327. Term var1 = new Variable("v1");
  328. List<Term> pts1 = new ArrayList<Term>();
  329. List<Term> pts2 = new ArrayList<Term>();
  330. pts1.add(cons1);
  331. pts1.add(cons2);
  332. pts1.add(var1);
  333. pts2.add(cons2);
  334. pts2.add(cons1);
  335. pts2.add(var1);
  336. Clause c1 = new Clause();
  337. Clause c2 = new Clause();
  338. Assert.assertTrue(c1.equals(c1));
  339. Assert.assertTrue(c2.equals(c2));
  340. Assert.assertTrue(c1.equals(c2));
  341. Assert.assertTrue(c2.equals(c1));
  342. // Check negatives
  343. c1.addNegativeLiteral(new Predicate("Pred1", pts1));
  344. Assert.assertFalse(c1.equals(c2));
  345. Assert.assertFalse(c2.equals(c1));
  346. c2.addNegativeLiteral(new Predicate("Pred1", pts1));
  347. Assert.assertTrue(c1.equals(c2));
  348. Assert.assertTrue(c2.equals(c1));
  349. c1.addNegativeLiteral(new Predicate("Pred2", pts2));
  350. Assert.assertFalse(c1.equals(c2));
  351. Assert.assertFalse(c2.equals(c1));
  352. c2.addNegativeLiteral(new Predicate("Pred2", pts2));
  353. Assert.assertTrue(c1.equals(c2));
  354. Assert.assertTrue(c2.equals(c1));
  355. // Check same but added in different order
  356. c1.addNegativeLiteral(new Predicate("Pred3", pts1));
  357. Assert.assertFalse(c1.equals(c2));
  358. Assert.assertFalse(c2.equals(c1));
  359. c1.addNegativeLiteral(new Predicate("Pred4", pts1));
  360. Assert.assertFalse(c1.equals(c2));
  361. Assert.assertFalse(c2.equals(c1));
  362. c2.addNegativeLiteral(new Predicate("Pred4", pts1));
  363. Assert.assertFalse(c1.equals(c2));
  364. Assert.assertFalse(c2.equals(c1));
  365. c2.addNegativeLiteral(new Predicate("Pred3", pts1));
  366. Assert.assertTrue(c1.equals(c2));
  367. Assert.assertTrue(c2.equals(c1));
  368. // Check positives
  369. c1.addPositiveLiteral(new Predicate("Pred1", pts1));
  370. Assert.assertFalse(c1.equals(c2));
  371. Assert.assertFalse(c2.equals(c1));
  372. c2.addPositiveLiteral(new Predicate("Pred1", pts1));
  373. Assert.assertTrue(c1.equals(c2));
  374. Assert.assertTrue(c2.equals(c1));
  375. c1.addPositiveLiteral(new Predicate("Pred2", pts2));
  376. Assert.assertFalse(c1.equals(c2));
  377. Assert.assertFalse(c2.equals(c1));
  378. c2.addPositiveLiteral(new Predicate("Pred2", pts2));
  379. Assert.assertTrue(c1.equals(c2));
  380. Assert.assertTrue(c2.equals(c1));
  381. // Check same but added in different order
  382. c1.addPositiveLiteral(new Predicate("Pred3", pts1));
  383. Assert.assertFalse(c1.equals(c2));
  384. Assert.assertFalse(c2.equals(c1));
  385. c1.addPositiveLiteral(new Predicate("Pred4", pts1));
  386. Assert.assertFalse(c1.equals(c2));
  387. Assert.assertFalse(c2.equals(c1));
  388. c2.addPositiveLiteral(new Predicate("Pred4", pts1));
  389. Assert.assertFalse(c1.equals(c2));
  390. Assert.assertFalse(c2.equals(c1));
  391. c2.addPositiveLiteral(new Predicate("Pred3", pts1));
  392. Assert.assertTrue(c1.equals(c2));
  393. Assert.assertTrue(c2.equals(c1));
  394. }
  395. @Test
  396. public void testComplexEquals() {
  397. FOLDomain domain = new FOLDomain();
  398. domain.addConstant("A");
  399. domain.addConstant("B");
  400. domain.addConstant("C");
  401. domain.addConstant("D");
  402. domain.addPredicate("P");
  403. domain.addPredicate("Animal");
  404. domain.addPredicate("Kills");
  405. domain.addFunction("F");
  406. domain.addFunction("SF0");
  407. FOLParser parser = new FOLParser(domain);
  408. CNFConverter cnfConverter = new CNFConverter(parser);
  409. Sentence s1 = parser.parse("((x1 = y1 AND y1 = z1) => x1 = z1)");
  410. Sentence s2 = parser.parse("((x2 = y2 AND F(y2) = z2) => F(x2) = z2)");
  411. CNF cnf1 = cnfConverter.convertToCNF(s1);
  412. CNF cnf2 = cnfConverter.convertToCNF(s2);
  413. Clause c1 = cnf1.getConjunctionOfClauses().get(0);
  414. Clause c2 = cnf2.getConjunctionOfClauses().get(0);
  415. Assert.assertFalse(c1.equals(c2));
  416. s1 = parser.parse("((x1 = y1 AND y1 = z1) => x1 = z1)");
  417. s2 = parser.parse("((x2 = y2 AND y2 = z2) => x2 = z2)");
  418. cnf1 = cnfConverter.convertToCNF(s1);
  419. cnf2 = cnfConverter.convertToCNF(s2);
  420. c1 = cnf1.getConjunctionOfClauses().get(0);
  421. c2 = cnf2.getConjunctionOfClauses().get(0);
  422. Assert.assertTrue(c1.equals(c2));
  423. s1 = parser.parse("((x1 = y1 AND y1 = z1) => x1 = z1)");
  424. s2 = parser.parse("((y2 = z2 AND x2 = y2) => x2 = z2)");
  425. cnf1 = cnfConverter.convertToCNF(s1);
  426. cnf2 = cnfConverter.convertToCNF(s2);
  427. c1 = cnf1.getConjunctionOfClauses().get(0);
  428. c2 = cnf2.getConjunctionOfClauses().get(0);
  429. Assert.assertTrue(c1.equals(c2));
  430. s1 = parser.parse("(((x1 = y1 AND y1 = z1) AND z1 = r1) => x1 = r1)");
  431. s2 = parser.parse("(((x2 = y2 AND y2 = z2) AND z2 = r2) => x2 = r2)");
  432. cnf1 = cnfConverter.convertToCNF(s1);
  433. cnf2 = cnfConverter.convertToCNF(s2);
  434. c1 = cnf1.getConjunctionOfClauses().get(0);
  435. c2 = cnf2.getConjunctionOfClauses().get(0);
  436. Assert.assertTrue(c1.equals(c2));
  437. s1 = parser.parse("(((x1 = y1 AND y1 = z1) AND z1 = r1) => x1 = r1)");
  438. s2 = parser.parse("(((z2 = r2 AND y2 = z2) AND x2 = y2) => x2 = r2)");
  439. cnf1 = cnfConverter.convertToCNF(s1);
  440. cnf2 = cnfConverter.convertToCNF(s2);
  441. c1 = cnf1.getConjunctionOfClauses().get(0);
  442. c2 = cnf2.getConjunctionOfClauses().get(0);
  443. Assert.assertTrue(c1.equals(c2));
  444. s1 = parser.parse("(((x1 = y1 AND y1 = z1) AND z1 = r1) => x1 = r1)");
  445. s2 = parser.parse("(((x2 = y2 AND y2 = z2) AND z2 = y2) => x2 = r2)");
  446. cnf1 = cnfConverter.convertToCNF(s1);
  447. cnf2 = cnfConverter.convertToCNF(s2);
  448. c1 = cnf1.getConjunctionOfClauses().get(0);
  449. c2 = cnf2.getConjunctionOfClauses().get(0);
  450. Assert.assertFalse(c1.equals(c2));
  451. s1 = parser
  452. .parse("(((((x1 = y1 AND y1 = z1) AND z1 = r1) AND r1 = q1) AND q1 = s1) => x1 = r1)");
  453. s2 = parser
  454. .parse("(((((x2 = y2 AND y2 = z2) AND z2 = r2) AND r2 = q2) AND q2 = s2) => x2 = r2)");
  455. cnf1 = cnfConverter.convertToCNF(s1);
  456. cnf2 = cnfConverter.convertToCNF(s2);
  457. c1 = cnf1.getConjunctionOfClauses().get(0);
  458. c2 = cnf2.getConjunctionOfClauses().get(0);
  459. Assert.assertTrue(c1.equals(c2));
  460. s1 = parser
  461. .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))))");
  462. s2 = parser
  463. .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))))");
  464. cnf1 = cnfConverter.convertToCNF(s1);
  465. cnf2 = cnfConverter.convertToCNF(s2);
  466. c1 = cnf1.getConjunctionOfClauses().get(0);
  467. c2 = cnf2.getConjunctionOfClauses().get(0);
  468. Assert.assertTrue(c1.equals(c2));
  469. }
  470. @Test
  471. public void testNonTrivialFactors() {
  472. FOLDomain domain = new FOLDomain();
  473. domain.addConstant("A");
  474. domain.addConstant("B");
  475. domain.addFunction("F");
  476. domain.addFunction("G");
  477. domain.addFunction("H");
  478. domain.addPredicate("P");
  479. domain.addPredicate("Q");
  480. FOLParser parser = new FOLParser(domain);
  481. // p(x,y), q(a,b), p(b,a), q(y,x)
  482. Clause c = new Clause();
  483. c.addPositiveLiteral((Predicate) parser.parse("P(x,y)"));
  484. c.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
  485. c.addNegativeLiteral((Predicate) parser.parse("P(B,A)"));
  486. c.addPositiveLiteral((Predicate) parser.parse("Q(y,x)"));
  487. Assert.assertEquals("[[~P(B,A), P(B,A), Q(A,B)]]", c
  488. .getNonTrivialFactors().toString());
  489. // p(x,y), q(a,b), p(b,a), q(y,x)
  490. c = new Clause();
  491. c.addPositiveLiteral((Predicate) parser.parse("P(x,y)"));
  492. c.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
  493. c.addNegativeLiteral((Predicate) parser.parse("P(B,A)"));
  494. c.addNegativeLiteral((Predicate) parser.parse("Q(y,x)"));
  495. Assert.assertEquals("[]", c.getNonTrivialFactors().toString());
  496. // p(x,f(y)), p(g(u),x), p(f(y),u)
  497. c = new Clause();
  498. c.addPositiveLiteral((Predicate) parser.parse("P(x,F(y))"));
  499. c.addPositiveLiteral((Predicate) parser.parse("P(G(u),x)"));
  500. c.addPositiveLiteral((Predicate) parser.parse("P(F(y),u)"));
  501. // Should be: [{P(F(c#),F(c#)),P(G(F(c#)),F(c#))}]
  502. c = c.getNonTrivialFactors().iterator().next();
  503. Literal p = c.getPositiveLiterals().get(0);
  504. Assert.assertEquals("P", p.getAtomicSentence().getSymbolicName());
  505. Function f = (Function) p.getAtomicSentence().getArgs().get(0);
  506. Assert.assertEquals("F", f.getFunctionName());
  507. Variable v = (Variable) f.getTerms().get(0);
  508. f = (Function) p.getAtomicSentence().getArgs().get(1);
  509. Assert.assertEquals("F", f.getFunctionName());
  510. Assert.assertEquals(v, f.getTerms().get(0));
  511. //
  512. p = c.getPositiveLiterals().get(1);
  513. f = (Function) p.getAtomicSentence().getArgs().get(0);
  514. Assert.assertEquals("G", f.getFunctionName());
  515. f = (Function) f.getTerms().get(0);
  516. Assert.assertEquals("F", f.getFunctionName());
  517. Assert.assertEquals(v, f.getTerms().get(0));
  518. f = (Function) p.getAtomicSentence().getArgs().get(1);
  519. Assert.assertEquals("F", f.getFunctionName());
  520. Assert.assertEquals(v, f.getTerms().get(0));
  521. // p(g(x)), q(x), p(f(a)), p(x), p(g(f(x))), q(f(a))
  522. c = new Clause();
  523. c.addPositiveLiteral((Predicate) parser.parse("P(G(x))"));
  524. c.addPositiveLiteral((Predicate) parser.parse("Q(x)"));
  525. c.addPositiveLiteral((Predicate) parser.parse("P(F(A))"));
  526. c.addPositiveLiteral((Predicate) parser.parse("P(x)"));
  527. c.addPositiveLiteral((Predicate) parser.parse("P(G(F(x)))"));
  528. c.addPositiveLiteral((Predicate) parser.parse("Q(F(A))"));
  529. Assert.assertEquals("[[P(F(A)), P(G(F(F(A)))), P(G(F(A))), Q(F(A))]]",
  530. c.getNonTrivialFactors().toString());
  531. }
  532. // Note: Tests derived from:
  533. // http://logic.stanford.edu/classes/cs157/2008/notes/chap09.pdf
  534. // page 16.
  535. @Test
  536. public void testIsTautology() {
  537. FOLDomain domain = new FOLDomain();
  538. domain.addConstant("A");
  539. domain.addPredicate("P");
  540. domain.addPredicate("Q");
  541. domain.addPredicate("R");
  542. domain.addFunction("F");
  543. FOLParser parser = new FOLParser(domain);
  544. // {p(f(a)),~p(f(a))}
  545. Clause c = new Clause();
  546. c.addPositiveLiteral((Predicate) parser.parse("P(F(A))"));
  547. Assert.assertFalse(c.isTautology());
  548. c.addNegativeLiteral((Predicate) parser.parse("P(F(A))"));
  549. Assert.assertTrue(c.isTautology());
  550. // {p(x),q(y),~q(y),r(z)}
  551. c = new Clause();
  552. c.addPositiveLiteral((Predicate) parser.parse("P(x)"));
  553. Assert.assertFalse(c.isTautology());
  554. c.addPositiveLiteral((Predicate) parser.parse("Q(y)"));
  555. Assert.assertFalse(c.isTautology());
  556. c.addNegativeLiteral((Predicate) parser.parse("Q(y)"));
  557. Assert.assertTrue(c.isTautology());
  558. c.addPositiveLiteral((Predicate) parser.parse("R(z)"));
  559. Assert.assertTrue(c.isTautology());
  560. // {~p(a),p(x)}
  561. c = new Clause();
  562. c.addNegativeLiteral((Predicate) parser.parse("P(A)"));
  563. Assert.assertFalse(c.isTautology());
  564. c.addPositiveLiteral((Predicate) parser.parse("P(x)"));
  565. Assert.assertFalse(c.isTautology());
  566. }
  567. // Note: Tests derived from:
  568. // http://logic.stanford.edu/classes/cs157/2008/lectures/lecture12.pdf
  569. // slides 17 and 18.
  570. @Test
  571. public void testSubsumes() {
  572. FOLDomain domain = new FOLDomain();
  573. domain.addConstant("A");
  574. domain.addConstant("B");
  575. domain.addConstant("C");
  576. domain.addConstant("D");
  577. domain.addConstant("E");
  578. domain.addConstant("F");
  579. domain.addConstant("G");
  580. domain.addConstant("H");
  581. domain.addConstant("I");
  582. domain.addConstant("J");
  583. domain.addPredicate("P");
  584. domain.addPredicate("Q");
  585. FOLParser parser = new FOLParser(domain);
  586. // Example
  587. // {~p(a,b),q(c)}
  588. Clause psi = new Clause();
  589. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  590. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  591. // {~p(x,y)}
  592. Clause phi = new Clause();
  593. phi.addNegativeLiteral((Predicate) parser.parse("P(x,y)"));
  594. Assert.assertTrue(phi.subsumes(psi));
  595. // Non-Example
  596. // {~p(x,b),q(x)}
  597. psi = new Clause();
  598. psi.addNegativeLiteral((Predicate) parser.parse("P(x,B)"));
  599. psi.addPositiveLiteral((Predicate) parser.parse("Q(x)"));
  600. // {~p(a,y)}
  601. phi = new Clause();
  602. phi.addNegativeLiteral((Predicate) parser.parse("P(A,y)"));
  603. // Reason for Non-Example:
  604. // {p(b,b)}
  605. // {~q(b)}
  606. Assert.assertFalse(phi.subsumes(psi));
  607. //
  608. // Additional Examples
  609. // Non-Example
  610. // {~p(x,b),q(z)}
  611. psi = new Clause();
  612. psi.addNegativeLiteral((Predicate) parser.parse("P(x,B)"));
  613. psi.addPositiveLiteral((Predicate) parser.parse("Q(z)"));
  614. // {~p(a,y)}
  615. phi = new Clause();
  616. phi.addNegativeLiteral((Predicate) parser.parse("P(A,y)"));
  617. Assert.assertFalse(phi.subsumes(psi));
  618. // Example
  619. // {~p(a,b),~p(w,z),q(c)}
  620. psi = new Clause();
  621. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  622. psi.addNegativeLiteral((Predicate) parser.parse("P(w,z)"));
  623. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  624. // {~p(x,y),~p(a,b)}
  625. phi = new Clause();
  626. phi.addNegativeLiteral((Predicate) parser.parse("P(x,y)"));
  627. phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  628. Assert.assertTrue(phi.subsumes(psi));
  629. // Non-Example
  630. // {~p(v,b),~p(w,z),q(c)}
  631. psi = new Clause();
  632. psi.addNegativeLiteral((Predicate) parser.parse("P(v,B)"));
  633. psi.addNegativeLiteral((Predicate) parser.parse("P(w,z)"));
  634. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  635. // {~p(x,y),~p(a,b)}
  636. phi = new Clause();
  637. phi.addNegativeLiteral((Predicate) parser.parse("P(x,y)"));
  638. phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  639. Assert.assertFalse(phi.subsumes(psi));
  640. // Example
  641. // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
  642. psi = new Clause();
  643. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  644. psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  645. psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  646. psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
  647. psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  648. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  649. // {~p(i,j)}
  650. phi = new Clause();
  651. phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  652. Assert.assertTrue(phi.subsumes(psi));
  653. // Example
  654. // {~p(a,b),~p(c,d),~p(e,f),q(c)}
  655. psi = new Clause();
  656. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  657. psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  658. psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  659. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  660. // {~p(e,f),~p(a,b),~p(c,d)}
  661. phi = new Clause();
  662. phi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  663. phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  664. phi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  665. Assert.assertTrue(phi.subsumes(psi));
  666. // Example
  667. // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
  668. psi = new Clause();
  669. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  670. psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  671. psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  672. psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
  673. psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  674. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  675. // {~p(i,j),~p(c,d)}
  676. phi = new Clause();
  677. phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  678. phi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  679. Assert.assertTrue(phi.subsumes(psi));
  680. // Non-Example
  681. // {~p(a,b),~p(x,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
  682. psi = new Clause();
  683. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  684. psi.addNegativeLiteral((Predicate) parser.parse("P(x,D)"));
  685. psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  686. psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
  687. psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  688. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  689. // {~p(i,j),~p(c,d)}
  690. phi = new Clause();
  691. phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  692. phi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  693. Assert.assertFalse(phi.subsumes(psi));
  694. // Example
  695. // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(c)}
  696. psi = new Clause();
  697. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  698. psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  699. psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  700. psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
  701. psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  702. psi.addPositiveLiteral((Predicate) parser.parse("Q(C)"));
  703. // {~p(i,j),~p(a,x)}
  704. phi = new Clause();
  705. phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  706. phi.addNegativeLiteral((Predicate) parser.parse("P(A,x)"));
  707. Assert.assertTrue(phi.subsumes(psi));
  708. // Example
  709. // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(a,b),q(c,d),q(e,f)}
  710. psi = new Clause();
  711. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  712. psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  713. psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  714. psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
  715. psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  716. psi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
  717. psi.addPositiveLiteral((Predicate) parser.parse("Q(C,D)"));
  718. psi.addPositiveLiteral((Predicate) parser.parse("Q(E,F)"));
  719. // {~p(i,j),~p(a,b),q(e,f),q(a,b)}
  720. phi = new Clause();
  721. phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  722. phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  723. phi.addPositiveLiteral((Predicate) parser.parse("Q(E,F)"));
  724. phi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
  725. Assert.assertTrue(phi.subsumes(psi));
  726. // Non-Example
  727. // {~p(a,b),~p(c,d),~p(e,f),~p(g,h),~p(i,j),q(a,b),q(c,d),q(e,f)}
  728. psi = new Clause();
  729. psi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  730. psi.addNegativeLiteral((Predicate) parser.parse("P(C,D)"));
  731. psi.addNegativeLiteral((Predicate) parser.parse("P(E,F)"));
  732. psi.addNegativeLiteral((Predicate) parser.parse("P(G,H)"));
  733. psi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  734. psi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
  735. psi.addPositiveLiteral((Predicate) parser.parse("Q(C,D)"));
  736. psi.addPositiveLiteral((Predicate) parser.parse("Q(E,F)"));
  737. // {~p(i,j),~p(a,b),q(e,f),q(a,b)}
  738. phi = new Clause();
  739. phi.addNegativeLiteral((Predicate) parser.parse("P(I,J)"));
  740. phi.addNegativeLiteral((Predicate) parser.parse("P(A,B)"));
  741. phi.addPositiveLiteral((Predicate) parser.parse("Q(E,A)"));
  742. phi.addPositiveLiteral((Predicate) parser.parse("Q(A,B)"));
  743. Assert.assertFalse(phi.subsumes(psi));
  744. }
  745. }