Skip to content

Commit 2207127

Browse files
ad71norvig
authored andcommitted
Minor update to planning.py (aimacode#923)
* PDDLs and Actions can now be defined using Exprs as well as Strings * Minor refactors
1 parent c65ac4e commit 2207127

File tree

1 file changed

+71
-26
lines changed

1 file changed

+71
-26
lines changed

planning.py

Lines changed: 71 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,25 @@ class PDDL:
1717

1818
def __init__(self, init, goals, actions):
1919
self.init = self.convert(init)
20-
self.goals = expr(goals)
20+
self.goals = self.convert(goals)
2121
self.actions = actions
2222

23-
def convert(self, init):
23+
def convert(self, clauses):
2424
"""Converts strings into exprs"""
25+
if not isinstance(clauses, Expr):
26+
if len(clauses) > 0:
27+
clauses = expr(clauses)
28+
else:
29+
clauses = []
2530
try:
26-
init = conjuncts(expr(init))
31+
clauses = conjuncts(clauses)
2732
except AttributeError:
28-
init = expr(init)
29-
return init
33+
clauses = clauses
34+
return clauses
3035

3136
def goal_test(self):
3237
"""Checks if the goals have been reached"""
33-
return all(goal in self.init for goal in conjuncts(self.goals))
38+
return all(goal in self.init for goal in self.goals)
3439

3540
def act(self, action):
3641
"""
@@ -61,34 +66,35 @@ class Action:
6166
"""
6267

6368
def __init__(self, action, precond, effect):
64-
action = expr(action)
69+
if isinstance(action, str):
70+
action = expr(action)
6571
self.name = action.op
6672
self.args = action.args
67-
self.precond, self.effect = self.convert(precond, effect)
73+
self.precond = self.convert(precond)
74+
self.effect = self.convert(effect)
6875

6976
def __call__(self, kb, args):
7077
return self.act(kb, args)
7178

72-
def convert(self, precond, effect):
79+
def convert(self, clauses):
7380
"""Converts strings into Exprs"""
81+
if isinstance(clauses, Expr):
82+
clauses = conjuncts(clauses)
83+
for i in range(len(clauses)):
84+
if clauses[i].op == '~':
85+
clauses[i] = expr('Not' + str(clauses[i].args[0]))
7486

75-
precond = precond.replace('~', 'Not')
76-
if len(precond) > 0:
77-
precond = expr(precond)
78-
effect = effect.replace('~', 'Not')
79-
if len(effect) > 0:
80-
effect = expr(effect)
87+
elif isinstance(clauses, str):
88+
clauses = clauses.replace('~', 'Not')
89+
if len(clauses) > 0:
90+
clauses = expr(clauses)
8191

82-
try:
83-
precond = conjuncts(precond)
84-
except AttributeError:
85-
pass
86-
try:
87-
effect = conjuncts(effect)
88-
except AttributeError:
89-
pass
92+
try:
93+
clauses = conjuncts(clauses)
94+
except AttributeError:
95+
pass
9096

91-
return precond, effect
97+
return clauses
9298

9399
def substitute(self, e, args):
94100
"""Replaces variables in expression with their respective Propositional symbol"""
@@ -138,10 +144,10 @@ def act(self, kb, args):
138144
def air_cargo():
139145
"""Air cargo problem"""
140146

141-
return PDDL(init='At(C1, SFO) & At(C2, JFK) & At(P1, SFO) & At(P2, JFK) & Cargo(C1) & Cargo(C2) & Plane(P1) & Plane(P2) & Airport(SFO) & Airport(JFK)',
147+
return PDDL(init='At(C1, SFO) & At(C2, JFK) & At(P1, SFO) & At(P2, JFK) & Cargo(C1) & Cargo(C2) & Plane(P1) & Plane(P2) & Airport(SFO) & Airport(JFK)',
142148
goals='At(C1, JFK) & At(C2, SFO)',
143149
actions=[Action('Load(c, p, a)',
144-
precond='At(c, a) & At(p, a) & Cargo(c) & Plane(p) & Airport(a)',
150+
precond='At(c, a) & At(p, a) & Cargo(c) & Plane(p) & Airport(a)',
145151
effect='In(c, p) & ~At(c, a)'),
146152
Action('Unload(c, p, a)',
147153
precond='In(c, p) & At(p, a) & Cargo(c) & Plane(p) & Airport(a)',
@@ -207,6 +213,25 @@ def shopping_problem():
207213
effect='At(y) & ~At(x)')])
208214

209215

216+
def socks_and_shoes():
217+
"""Socks and shoes problem"""
218+
219+
return PDDL(init='',
220+
goals='RightShoeOn & LeftShoeOn',
221+
actions=[Action('RightShoe',
222+
precond='RightSockOn',
223+
effect='RightShoeOn'),
224+
Action('RightSock',
225+
precond='',
226+
effect='RightSockOn'),
227+
Action('LeftShoe',
228+
precond='LeftSockOn',
229+
effect='LeftShoeOn'),
230+
Action('LeftSock',
231+
precond='',
232+
effect='LeftSockOn')])
233+
234+
210235
class Level:
211236
"""
212237
Contains the state of the planning problem
@@ -559,6 +584,26 @@ def goal_test(kb, goals):
559584
return None
560585

561586

587+
def socks_and_shoes_graphplan():
588+
pddl = socks_and_shoes()
589+
graphplan = GraphPlan(pddl)
590+
591+
def goal_test(kb, goals):
592+
return all(kb.ask(q) is not False for q in goals)
593+
594+
goals = expr('RightShoeOn, LeftShoeOn')
595+
596+
while True:
597+
if (goal_test(graphplan.graph.levels[-1].kb, goals) and graphplan.graph.non_mutex_goals(goals, -1)):
598+
solution = graphplan.extract_solution(goals, -1)
599+
if solution:
600+
return solution
601+
602+
graphplan.graph.expand_graph()
603+
if len(graphplan.graph.levels) >= 2 and graphplan.check_leveloff():
604+
return None
605+
606+
562607
def linearize(solution):
563608
"""Converts a level-ordered solution into a linear solution"""
564609

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy