Advertisement
Guest User

Untitled

a guest
Dec 13th, 2018
87
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.98 KB | None | 0 0
  1.  
  2. from itertools import chain, combinations
  3. from aimacode.planning import Action
  4. from aimacode.utils import expr
  5.  
  6. from layers import BaseActionLayer, BaseLiteralLayer, makeNoOp, make_node
  7.  
  8.  
  9. class ActionLayer(BaseActionLayer):
  10.  
  11. def _inconsistent_effects(self, actionA, actionB):
  12. """ Return True if an effect of one action negates an effect of the other
  13.  
  14. Hints:
  15. (1) `~Literal` can be used to logically negate a literal
  16. (2) `self.children` contains a map from actions to effects
  17.  
  18. See Also
  19. --------
  20. layers.ActionNode
  21. """
  22. # TODO: implement this function
  23. return any([action in actionA.effects for ~action in actionB.effects])
  24.  
  25. def _interference(self, actionA, actionB):
  26. """ Return True if the effects of either action negate the preconditions of the other
  27.  
  28. Hints:
  29. (1) `~Literal` can be used to logically negate a literal
  30. (2) `self.parents` contains a map from actions to preconditions
  31.  
  32. See Also
  33. --------
  34. layers.ActionNode
  35. """
  36. # TODO: implement this function
  37. return any([action in actionA.preconditions for ~action in actionB.effects] +
  38. [action in actionB.preconditions for ~action in actionA.effects])
  39.  
  40. def _competing_needs(self, actionA, actionB):
  41. """ Return True if any preconditions of the two actions are pairwise mutex in the parent layer
  42.  
  43. Hints:
  44. (1) `self.parent_layer` contains a reference to the previous literal layer
  45. (2) `self.parents` contains a map from actions to preconditions
  46.  
  47. See Also
  48. --------
  49. layers.ActionNode
  50. layers.BaseLayer.parent_layer
  51. """
  52. # TODO: implement this function
  53. return any(self.parent_layer.is_mutex(a, b) or self.parent_layer.is_mutex(b, a)
  54. for a in actionA.preconditions for b in actionB.preconditions)
  55.  
  56. class LiteralLayer(BaseLiteralLayer):
  57.  
  58. def _inconsistent_support(self, literalA, literalB):
  59. """ Return True if all ways to achieve both literals are pairwise mutex in the parent layer
  60.  
  61. Hints:
  62. (1) `self.parent_layer` contains a reference to the previous action layer
  63. (2) `self.parents` contains a map from literals to actions in the parent layer
  64.  
  65. See Also
  66. --------
  67. layers.BaseLayer.parent_layer
  68. """
  69. # TODO: implement this function
  70. return all(self.parent_layer.is_mutex(a, b) and self.parent_layer.is_mutex(b, a)
  71. for a in self.parents[literalA] for b in self.parents[literalB])
  72.  
  73. def _negation(self, literalA, literalB):
  74. """ Return True if two literals are negations of each other """
  75. # TODO: implement this function
  76. return literalA == ~literalB
  77.  
  78.  
  79. class PlanningGraph:
  80. def __init__(self, problem, state, serialize=True, ignore_mutexes=False):
  81. """
  82. Parameters
  83. ----------
  84. problem : PlanningProblem
  85. An instance of the PlanningProblem class
  86.  
  87. state : tuple(bool)
  88. An ordered sequence of True/False values indicating the literal value
  89. of the corresponding fluent in problem.state_map
  90.  
  91. serialize : bool
  92. Flag indicating whether to serialize non-persistence actions. Actions
  93. should NOT be serialized for regression search (e.g., GraphPlan), and
  94. _should_ be serialized if the planning graph is being used to estimate
  95. a heuristic
  96. """
  97. self._serialize = serialize
  98. self._is_leveled = False
  99. self._ignore_mutexes = ignore_mutexes
  100. self.goal = set(problem.goal)
  101.  
  102. # make no-op actions that persist every literal to the next layer
  103. no_ops = [make_node(n, no_op=True) for n in chain(*(makeNoOp(s) for s in problem.state_map))]
  104. self._actionNodes = no_ops + [make_node(a) for a in problem.actions_list]
  105.  
  106. # initialize the planning graph by finding the literals that are in the
  107. # first layer and finding the actions they they should be connected to
  108. literals = [s if f else ~s for f, s in zip(state, problem.state_map)]
  109. layer = LiteralLayer(literals, ActionLayer(), self._ignore_mutexes)
  110. layer.update_mutexes()
  111. self.literal_layers = [layer]
  112. self.action_layers = []
  113.  
  114. def h_levelsum(self):
  115. """ Calculate the level sum heuristic for the planning graph
  116.  
  117. The level sum is the sum of the level costs of all the goal literals
  118. combined. The "level cost" to achieve any single goal literal is the
  119. level at which the literal first appears in the planning graph. Note
  120. that the level cost is **NOT** the minimum number of actions to
  121. achieve a single goal literal.
  122.  
  123. For example, if Goal_1 first appears in level 0 of the graph (i.e.,
  124. it is satisfied at the root of the planning graph) and Goal_2 first
  125. appears in level 3, then the levelsum is 0 + 3 = 3.
  126.  
  127. Hints
  128. -----
  129. (1) See the pseudocode folder for help on a simple implementation
  130. (2) You can implement this function more efficiently than the
  131. sample pseudocode if you expand the graph one level at a time
  132. and accumulate the level cost of each goal rather than filling
  133. the whole graph at the start.
  134.  
  135. See Also
  136. --------
  137. Russell-Norvig 10.3.1 (3rd Edition)
  138. """
  139. # TODO: implement this function
  140. level = 0
  141. for goal in self.goal:
  142. level = 0
  143. for layer in self.literal_layers:
  144. level++
  145. if g in layer:
  146. break
  147. return level
  148. #raise NotImplementedError
  149.  
  150. def h_maxlevel(self):
  151. """ Calculate the max level heuristic for the planning graph
  152.  
  153. The max level is the largest level cost of any single goal fluent.
  154. The "level cost" to achieve any single goal literal is the level at
  155. which the literal first appears in the planning graph. Note that
  156. the level cost is **NOT** the minimum number of actions to achieve
  157. a single goal literal.
  158.  
  159. For example, if Goal1 first appears in level 1 of the graph and
  160. Goal2 first appears in level 3, then the levelsum is max(1, 3) = 3.
  161.  
  162. Hints
  163. -----
  164. (1) See the pseudocode folder for help on a simple implementation
  165. (2) You can implement this function more efficiently if you expand
  166. the graph one level at a time until the last goal is met rather
  167. than filling the whole graph at the start.
  168.  
  169. See Also
  170. --------
  171. Russell-Norvig 10.3.1 (3rd Edition)
  172.  
  173. Notes
  174. -----
  175. WARNING: you should expect long runtimes using this heuristic with A*
  176. """
  177. # TODO: implement maxlevel heuristic
  178. #raise NotImplementedError
  179. sol = 0
  180. for g in self.goal:
  181. for idx,layer in enumerate(self.literal_layers):
  182. if g in layer:
  183. sol = max(sol,idx)
  184. break
  185. return sol
  186. def h_setlevel(self):
  187. """ Calculate the set level heuristic for the planning graph
  188.  
  189. The set level of a planning graph is the first level where all goals
  190. appear such that no pair of goal literals are mutex in the last
  191. layer of the planning graph.
  192.  
  193. Hints
  194. -----
  195. (1) See the pseudocode folder for help on a simple implementation
  196. (2) You can implement this function more efficiently if you expand
  197. the graph one level at a time until you find the set level rather
  198. than filling the whole graph at the start.
  199.  
  200. See Also
  201. --------
  202. Russell-Norvig 10.3.1 (3rd Edition)
  203.  
  204. Notes
  205. -----
  206. WARNING: you should expect long runtimes using this heuristic on complex problems
  207. """
  208. # TODO: implement setlevel heuristic
  209. raise NotImplementedError
  210.  
  211. ##############################################################################
  212. # DO NOT MODIFY CODE BELOW THIS LINE #
  213. ##############################################################################
  214.  
  215. def fill(self, maxlevels=-1):
  216. """ Extend the planning graph until it is leveled, or until a specified number of
  217. levels have been added
  218.  
  219. Parameters
  220. ----------
  221. maxlevels : int
  222. The maximum number of levels to extend before breaking the loop. (Starting with
  223. a negative value will never interrupt the loop.)
  224.  
  225. Notes
  226. -----
  227. YOU SHOULD NOT THIS FUNCTION TO COMPLETE THE PROJECT, BUT IT MAY BE USEFUL FOR TESTING
  228. """
  229. while not self._is_leveled:
  230. if maxlevels == 0: break
  231. self._extend()
  232. maxlevels -= 1
  233. return self
  234.  
  235. def _extend(self):
  236. """ Extend the planning graph by adding both a new action layer and a new literal layer
  237.  
  238. The new action layer contains all actions that could be taken given the positive AND
  239. negative literals in the leaf nodes of the parent literal level.
  240.  
  241. The new literal layer contains all literals that could result from taking each possible
  242. action in the NEW action layer.
  243. """
  244. if self._is_leveled: return
  245.  
  246. parent_literals = self.literal_layers[-1]
  247. parent_actions = parent_literals.parent_layer
  248. action_layer = ActionLayer(parent_actions, parent_literals, self._serialize, self._ignore_mutexes)
  249. literal_layer = LiteralLayer(parent_literals, action_layer, self._ignore_mutexes)
  250.  
  251. for action in self._actionNodes:
  252. # actions in the parent layer are skipped because are added monotonically to planning graphs,
  253. # which is performed automatically in the ActionLayer and LiteralLayer constructors
  254. if action not in parent_actions and action.preconditions <= parent_literals:
  255. action_layer.add(action)
  256. literal_layer |= action.effects
  257.  
  258. # add two-way edges in the graph connecting the parent layer with the new action
  259. parent_literals.add_outbound_edges(action, action.preconditions)
  260. action_layer.add_inbound_edges(action, action.preconditions)
  261.  
  262. # # add two-way edges in the graph connecting the new literaly layer with the new action
  263. action_layer.add_outbound_edges(action, action.effects)
  264. literal_layer.add_inbound_edges(action, action.effects)
  265.  
  266. action_layer.update_mutexes()
  267. literal_layer.update_mutexes()
  268. self.action_layers.append(action_layer)
  269. self.literal_layers.append(literal_layer)
  270. self._is_leveled = literal_layer == action_layer.parent_layer
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement