@@ -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):
138144def 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+
210235class 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+
562607def linearize (solution ):
563608 """Converts a level-ordered solution into a linear solution"""
564609
0 commit comments