@@ -29,7 +29,6 @@ def __goal_count_heuristic(self, state):
2929 count += 1
3030 return count
3131
32-
3332class DeleteRelaxationHeuristic :
3433 def __init__ (self , automated_planner , heuristic_key ):
3534 class DRHCache :
@@ -127,3 +126,109 @@ def __facts_eq(self, facts_dict, facts_set):
127126 if not (str (f ) in fact_costs_str .keys ()):
128127 return False
129128 return True
129+
130+ class CriticalPathHeuristic :
131+ def __init__ (self , automated_planner , critical_path_level = 1 ):
132+ class CPCache :
133+ def __init__ (self , domain = None , axioms = None , preconds = None , additions = None ):
134+ self .domain = domain
135+ self .axioms = axioms
136+ self .preconds = preconds
137+ self .additions = additions
138+
139+ self .automated_planner = automated_planner
140+ self .cache = CPCache ()
141+ if critical_path_level > 3 :
142+ logging .warning ("Critical Path level is only implemented until 3, forcing it to 3." )
143+ self .critical_path_level = 3
144+ if critical_path_level < 1 :
145+ logging .warning ("Critical Path level has to be at least 1, forcing it to 1." )
146+ self .critical_path_level = 1
147+ else :
148+ self .critical_path_level = critical_path_level
149+ self .has_been_precomputed = False
150+ self .__pre_compute ()
151+ # return self.heuristic_keys[self.current_h](state)
152+
153+ def compute (self , state ):
154+ if not self .has_been_precomputed :
155+ self .__pre_compute ()
156+ domain = self .cache .domain
157+ goals = self .automated_planner .goals
158+ types = state .types
159+ facts = state .facts
160+ fact_costs = self .automated_planner .pddl .init_facts_costs (facts )
161+ while True :
162+ facts , state = self .automated_planner .pddl .get_facts_and_state (
163+ fact_costs , types
164+ )
165+ if self .automated_planner .satisfies (goals , state ):
166+ costs = []
167+ fact_costs_str = dict ([(str (k ), val ) for k , val in fact_costs .items ()])
168+ if self .critical_path_level == 1 :
169+ for g in goals :
170+ if str (g ) in fact_costs_str :
171+ costs .append (fact_costs_str [str (g )])
172+ if self .critical_path_level == 2 :
173+ pairs_of_goals = [(g1 , g2 ) for g1 in goals for g2 in goals if g1 != g2 ]
174+ for gs in pairs_of_goals :
175+ if str (gs [0 ]) in fact_costs_str and str (gs [1 ]) in fact_costs_str :
176+ costs .append (fact_costs_str [str (gs [0 ])] + fact_costs_str [str (gs [1 ])])
177+ if self .critical_path_level == 3 :
178+ triplets_of_goals = [(g1 , g2 , g3 ) for g1 in goals for g2 in goals for g3 in goals if g1 != g2 and g1 != g3 and g2 != g3 ]
179+ for gs in triplets_of_goals :
180+ if str (gs [0 ]) in fact_costs_str and str (gs [1 ]) in fact_costs_str and str (gs [2 ]) in fact_costs_str :
181+ costs .append (fact_costs_str [str (gs [0 ])] + fact_costs_str [str (gs [1 ])] + fact_costs_str [str (gs [2 ])])
182+ costs .insert (0 , 0 )
183+ return max (costs )
184+
185+ for ax in self .cache .axioms :
186+ fact_costs = (
187+ self .automated_planner .pddl .compute_costs_one_step_derivation (
188+ facts , fact_costs , ax , "max"
189+ )
190+ )
191+
192+ actions = self .automated_planner .available_actions (state )
193+ for act in actions :
194+ fact_costs = self .automated_planner .pddl .compute_cost_action_effect (
195+ fact_costs , act , domain , self .cache .additions , "max"
196+ )
197+
198+ if len (fact_costs ) == self .automated_planner .pddl .length (
199+ facts
200+ ) and self .__facts_eq (fact_costs , facts ):
201+ break
202+
203+ return float ("inf" )
204+
205+ def __pre_compute (self ):
206+ if self .has_been_precomputed :
207+ return
208+ domain = self .automated_planner .domain
209+ domain , axioms = self .automated_planner .pddl .compute_hsp_axioms (domain )
210+ # preconditions = dict()
211+ additions = dict ()
212+ self .automated_planner .pddl .cache_global_preconditions (domain )
213+ for name , definition in domain .actions .items ():
214+ additions [name ] = self .automated_planner .pddl .effect_diff (
215+ definition .effect
216+ ).add
217+ self .cache .additions = additions
218+ self .cache .preconds = self .automated_planner .pddl .g_preconditions
219+ self .cache .domain = domain
220+ self .cache .axioms = axioms
221+ self .has_been_precomputed = True
222+
223+ def __h_add (self , costs ):
224+ return sum (costs )
225+
226+ def __h_max (self , costs ):
227+ return max (costs )
228+
229+ def __facts_eq (self , facts_dict , facts_set ):
230+ fact_costs_str = dict ([(str (k ), val ) for k , val in facts_dict .items ()])
231+ for f in facts_set :
232+ if not (str (f ) in fact_costs_str .keys ()):
233+ return False
234+ return True
0 commit comments