test_my_planning_graph.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. import os
  2. import sys
  3. import unittest
  4. from aimacode.utils import expr
  5. from aimacode.planning import Action
  6. from example_have_cake import have_cake
  7. from my_planning_graph import (
  8. PlanningGraph, PgNode_a, PgNode_s, mutexify
  9. )
  10. class TestPlanningGraphLevels(unittest.TestCase):
  11. def setUp(self):
  12. self.p = have_cake()
  13. self.pg = PlanningGraph(self.p, self.p.initial)
  14. def test_add_action_level(self):
  15. # for level, nodeset in enumerate(self.pg.a_levels):
  16. # for node in nodeset:
  17. # print("Level {}: {}{})".format(level, node.action.name, node.action.args))
  18. self.assertEqual(len(self.pg.a_levels[0]), 3, len(self.pg.a_levels[0]))
  19. self.assertEqual(len(self.pg.a_levels[1]), 6, len(self.pg.a_levels[1]))
  20. def test_add_literal_level(self):
  21. # for level, nodeset in enumerate(self.pg.s_levels):
  22. # for node in nodeset:
  23. # print("Level {}: {})".format(level, node.literal))
  24. self.assertEqual(len(self.pg.s_levels[0]), 2, len(self.pg.s_levels[0]))
  25. self.assertEqual(len(self.pg.s_levels[1]), 4, len(self.pg.s_levels[1]))
  26. self.assertEqual(len(self.pg.s_levels[2]), 4, len(self.pg.s_levels[2]))
  27. class TestPlanningGraphMutex(unittest.TestCase):
  28. def setUp(self):
  29. self.p = have_cake()
  30. self.pg = PlanningGraph(self.p, self.p.initial)
  31. # some independent nodes for testing mutex
  32. self.na1 = PgNode_a(Action(expr('Go(here)'),
  33. [[], []], [[expr('At(here)')], []]))
  34. self.na2 = PgNode_a(Action(expr('Go(there)'),
  35. [[], []], [[expr('At(there)')], []]))
  36. self.na3 = PgNode_a(Action(expr('Noop(At(there))'),
  37. [[expr('At(there)')], []], [[expr('At(there)')], []]))
  38. self.na4 = PgNode_a(Action(expr('Noop(At(here))'),
  39. [[expr('At(here)')], []], [[expr('At(here)')], []]))
  40. self.na5 = PgNode_a(Action(expr('Reverse(At(here))'),
  41. [[expr('At(here)')], []], [[], [expr('At(here)')]]))
  42. self.ns1 = PgNode_s(expr('At(here)'), True)
  43. self.ns2 = PgNode_s(expr('At(there)'), True)
  44. self.ns3 = PgNode_s(expr('At(here)'), False)
  45. self.ns4 = PgNode_s(expr('At(there)'), False)
  46. self.na1.children.add(self.ns1)
  47. self.ns1.parents.add(self.na1)
  48. self.na2.children.add(self.ns2)
  49. self.ns2.parents.add(self.na2)
  50. self.na1.parents.add(self.ns3)
  51. self.na2.parents.add(self.ns4)
  52. def test_serialize_mutex(self):
  53. self.assertTrue(PlanningGraph.serialize_actions(self.pg, self.na1, self.na2),
  54. "Two persistence action nodes not marked as mutex")
  55. self.assertFalse(PlanningGraph.serialize_actions(self.pg, self.na3, self.na4), "Two No-Ops were marked mutex")
  56. self.assertFalse(PlanningGraph.serialize_actions(self.pg, self.na1, self.na3),
  57. "No-op and persistence action incorrectly marked as mutex")
  58. def test_inconsistent_effects_mutex(self):
  59. self.assertTrue(PlanningGraph.inconsistent_effects_mutex(self.pg, self.na4, self.na5),
  60. "Canceling effects not marked as mutex")
  61. self.assertFalse(PlanningGraph.inconsistent_effects_mutex(self.pg, self.na1, self.na2),
  62. "Non-Canceling effects incorrectly marked as mutex")
  63. def test_interference_mutex(self):
  64. self.assertTrue(PlanningGraph.interference_mutex(self.pg, self.na4, self.na5),
  65. "Precondition from one node opposite of effect of other node should be mutex")
  66. self.assertTrue(PlanningGraph.interference_mutex(self.pg, self.na5, self.na4),
  67. "Precondition from one node opposite of effect of other node should be mutex")
  68. self.assertFalse(PlanningGraph.interference_mutex(self.pg, self.na1, self.na2),
  69. "Non-interfering incorrectly marked mutex")
  70. def test_competing_needs_mutex(self):
  71. self.assertFalse(PlanningGraph.competing_needs_mutex(self.pg, self.na1, self.na2),
  72. "Non-competing action nodes incorrectly marked as mutex")
  73. mutexify(self.ns3, self.ns4)
  74. self.assertTrue(PlanningGraph.competing_needs_mutex(self.pg, self.na1, self.na2),
  75. "Opposite preconditions from two action nodes not marked as mutex")
  76. def test_negation_mutex(self):
  77. self.assertTrue(PlanningGraph.negation_mutex(self.pg, self.ns1, self.ns3),
  78. "Opposite literal nodes not found to be Negation mutex")
  79. self.assertFalse(PlanningGraph.negation_mutex(self.pg, self.ns1, self.ns2),
  80. "Same literal nodes found to be Negation mutex")
  81. def test_inconsistent_support_mutex(self):
  82. self.assertFalse(PlanningGraph.inconsistent_support_mutex(self.pg, self.ns1, self.ns2),
  83. "Independent node paths should NOT be inconsistent-support mutex")
  84. mutexify(self.na1, self.na2)
  85. self.assertTrue(PlanningGraph.inconsistent_support_mutex(self.pg, self.ns1, self.ns2),
  86. "Mutex parent actions should result in inconsistent-support mutex")
  87. self.na6 = PgNode_a(Action(expr('Go(everywhere)'),
  88. [[], []], [[expr('At(here)'), expr('At(there)')], []]))
  89. self.na6.children.add(self.ns1)
  90. self.ns1.parents.add(self.na6)
  91. self.na6.children.add(self.ns2)
  92. self.ns2.parents.add(self.na6)
  93. self.na6.parents.add(self.ns3)
  94. self.na6.parents.add(self.ns4)
  95. mutexify(self.na1, self.na6)
  96. mutexify(self.na2, self.na6)
  97. self.assertFalse(PlanningGraph.inconsistent_support_mutex(
  98. self.pg, self.ns1, self.ns2),
  99. "If one parent action can achieve both states, should NOT be inconsistent-support mutex, even if parent actions are themselves mutex")
  100. class TestPlanningGraphHeuristics(unittest.TestCase):
  101. def setUp(self):
  102. self.p = have_cake()
  103. self.pg = PlanningGraph(self.p, self.p.initial)
  104. def test_levelsum(self):
  105. self.assertEqual(self.pg.h_levelsum(), 1)
  106. if __name__ == '__main__':
  107. unittest.main()