00001
00002
00003 import copy
00004
00005 import conditions
00006 import effects
00007 import f_expression
00008 import pddl_types
00009
00010 class Action(object):
00011 def __init__(self, name, parameters, precondition, effects):
00012 self.name = name
00013 self.parameters = parameters
00014 self.condition = precondition
00015 self.effects = effects
00016 self.uniquify_variables()
00017 def parse(alist):
00018 iterator = iter(alist)
00019 assert iterator.next() == ":action"
00020 name = iterator.next()
00021 parameters_tag_opt = iterator.next()
00022 if parameters_tag_opt == ":parameters":
00023 parameters = pddl_types.parse_typed_list(iterator.next(),
00024 only_variables=True)
00025 precondition_tag_opt = iterator.next()
00026 else:
00027 parameters = []
00028 precondition_tag_opt = parameters_tag_opt
00029 if precondition_tag_opt == ":precondition":
00030 precondition = conditions.parse_condition(iterator.next())
00031 effect_tag = iterator.next()
00032 else:
00033 precondition = conditions.Conjunction([])
00034 effect_tag = precondition_tag_opt
00035 assert effect_tag == ":effect"
00036 effect_list = iterator.next()
00037 eff = []
00038 effects.parse_effects(effect_list,eff)
00039 for rest in iterator:
00040 assert False, rest
00041 return Action(name, parameters, precondition, eff)
00042 parse = staticmethod(parse)
00043 def dump(self):
00044 print "%s(%s)" % (self.name, ", ".join(map(str, self.parameters)))
00045 print "Precondition:"
00046 self.condition.dump()
00047 print "Effects:"
00048 for eff in self.effects:
00049 eff.dump()
00050 def uniquify_variables(self):
00051 self.type_map = dict([(par.name, par.type) for par in self.parameters])
00052 self.condition = self.condition.uniquify_variables(self.type_map)
00053 for effect in self.effects:
00054 effect.uniquify_variables(self.type_map)
00055 def relaxed(self):
00056 new_effects = []
00057 for eff in self.effects:
00058 relaxed_eff = eff.relaxed()
00059 if relaxed_eff:
00060 new_effects.append(relaxed_eff)
00061 return Action(self.name, self.parameters,
00062 self.condition.relaxed().simplified(),
00063 new_effects)
00064 def untyped(self):
00065
00066
00067
00068 result = copy.copy(self)
00069 parameter_atoms = [par.to_untyped_strips() for par in self.parameters]
00070 new_precondition = self.condition.untyped()
00071 result.condition = conditions.Conjunction(parameter_atoms + [new_precondition])
00072 result.effects = [eff.untyped() for eff in self.effects]
00073 return result
00074
00075 def instantiate(self, var_mapping, init_facts, fluent_facts, init_function_vals,
00076 fluent_functions, task, new_axiom, new_modules, objects_by_type):
00077 """Return a PropositionalAction which corresponds to the instantiation of
00078 this action with the arguments in var_mapping. Only fluent parts of the
00079 conditions (those in fluent_facts) are included. init_facts are evaluated
00080 whilte instantiating.
00081 Precondition and effect conditions must be normalized for this to work.
00082 Returns None if var_mapping does not correspond to a valid instantiation
00083 (because it has impossible preconditions or an empty effect list.)"""
00084 arg_list = [var_mapping[conditions.Variable(par.name)].name for par in self.parameters]
00085 name = "(%s %s)" % (self.name, " ".join(arg_list))
00086
00087 precondition = []
00088 try:
00089 self.condition.instantiate(var_mapping, init_facts, fluent_facts,
00090 init_function_vals, fluent_functions, task,
00091 new_axiom, new_modules, precondition)
00092 except conditions.Impossible:
00093 return None
00094 effects = []
00095 for eff in self.effects:
00096 eff.instantiate(var_mapping, init_facts, fluent_facts,
00097 init_function_vals, fluent_functions, task,
00098 new_axiom, new_modules, objects_by_type, effects)
00099 if effects:
00100 return PropositionalAction(name, precondition, effects)
00101 else:
00102 return None
00103
00104 class DurativeAction(object):
00105 def __init__(self, name, parameters, duration, conditions, effects):
00106 self.name = name
00107 self.parameters = parameters
00108 self.orig_parameter_length = len(parameters)
00109 self.duration = duration
00110 self.condition = conditions
00111 assert len(effects)==2
00112 self.effects = effects
00113 self.uniquify_variables()
00114 def parse(alist):
00115 iterator = iter(alist)
00116 assert iterator.next() == ":durative-action"
00117 name = iterator.next()
00118 print "Parsing durative-action", name
00119 parameters_tag_opt = iterator.next()
00120 if parameters_tag_opt == ":parameters":
00121 parameters = pddl_types.parse_typed_list(iterator.next(),
00122 only_variables=True)
00123 duration_tag = iterator.next()
00124 else:
00125 parameters = []
00126 duration_tag = parameters_tag_opt
00127 assert duration_tag == ":duration"
00128 duration_list = iterator.next()
00129 if duration_list[0] == "and":
00130 duration_list = duration_list[1:]
00131 else:
00132 duration_list = [duration_list]
00133 duration_start = []
00134 duration_end = []
00135 for item in duration_list:
00136 duration = duration_start
00137 if item[0] == "at":
00138 if item[1] == "end":
00139 duration = duration_end
00140 item = item[2]
00141 assert item[0] in ("<=",">=","=")
00142 if len(item) == 3:
00143 assert item[1] == "?duration"
00144 op = item[0]
00145 value = f_expression.parse_expression(item[2])
00146 duration += [(op,value)]
00147 else:
00148 assert item[1] == "?duration"
00149 op = item[0]
00150 mod_list = item[2:]
00151
00152 value = conditions.parse_condition(mod_list)
00153
00154 duration += [(op,value)]
00155 pass
00156 condition_tag = iterator.next()
00157 if condition_tag == ":condition":
00158 condition = conditions.parse_durative_condition(iterator.next())
00159 effect_tag = iterator.next()
00160 else:
00161 condition = conditions.parse_durative_condition([])
00162 effect_tag = condition_tag
00163 assert effect_tag == ":effect"
00164
00165 effect_list = iterator.next()
00166 effect = [[],[]]
00167 effects.parse_durative_effects(effect_list, effect)
00168 for rest in iterator:
00169 assert False, rest
00170 return DurativeAction(name, parameters, (duration_start,duration_end), condition, effect)
00171 parse = staticmethod(parse)
00172 def dump(self):
00173 if self.orig_parameter_length != len(self.parameters):
00174 print "%s(%s, (%s))" % (self.name,
00175 ", ".join(map(str, self.parameters[0:self.orig_parameter_length])),
00176 ", ".join(map(str, self.parameters[self.orig_parameter_length:])))
00177 else:
00178 print "%s(%s)" % (self.name, ", ".join(map(str, self.parameters)))
00179 if len(self.duration[0]) > 0:
00180 print "duration (values from start):"
00181 for (op, val) in self.duration[0]:
00182 print " " + op
00183 val.dump(" ")
00184 if len(self.duration[1]) > 0:
00185 print "duration (values from end):"
00186 for (op, val) in self.duration[1]:
00187 print " " + op
00188 val.dump(" ")
00189 print "start condition:"
00190 self.condition[0].dump()
00191 print "over all condition:"
00192 self.condition[1].dump()
00193 print "end condition:"
00194 self.condition[2].dump()
00195 print "start effects:"
00196 for eff in self.effects[0]:
00197 eff.dump()
00198 print "end effects:"
00199 for eff in self.effects[1]:
00200 eff.dump()
00201 def __str__(self):
00202 return "<Action %s>" % self.name
00203 def uniquify_variables(self):
00204 self.type_map = dict([(par.name, par.type) for par in self.parameters])
00205 for index, condition in enumerate(self.condition):
00206 self.condition[index] = condition.uniquify_variables(self.type_map)
00207 for effects in self.effects:
00208 for effect in effects:
00209 effect.uniquify_variables(self.type_map)
00210 def instantiate(self, var_mapping, init_facts, fluent_facts, init_function_vals,
00211 fluent_functions, task, new_axiom, new_modules, objects_by_type):
00212 """Return a PropositionalDurativeAction which corresponds to the instantiation of
00213 this action with the arguments in var_mapping. Only fluent parts of the
00214 conditions (those in fluent_facts) are included. init_facts are evaluated
00215 whilte instantiating.
00216 Precondition and effect conditions must be normalized for this to work.
00217 Returns None if var_mapping does not correspond to a valid instantiation
00218 (because it has impossible preconditions or an empty effect list.)"""
00219
00220 arg_list = [var_mapping[conditions.Variable(par.name)].name for par in self.parameters]
00221 name = "(%s %s)" % (self.name, " ".join(arg_list[:self.orig_parameter_length]))
00222
00223 try:
00224 inst_duration = [[],[]]
00225 for dura in (0, 1):
00226 for (op, pne) in self.duration[dura]:
00227 if isinstance(pne, conditions.ModuleCall):
00228 result = []
00229 pne.instantiate(var_mapping, init_facts, fluent_facts,
00230 init_function_vals, fluent_functions, task, new_axiom, new_modules, result)
00231 assert len(result) == 1, "Something when wrong when instantiating cost module"
00232 inst_duration[dura].append((op, result[0]))
00233 else:
00234 inst_duration[dura].append((op,pne.instantiate(var_mapping, fluent_functions,
00235 init_function_vals, task, new_axiom)))
00236 except ValueError, e:
00237 print "dropped action %s" % name
00238 print "Error: %s" % e
00239 return None
00240
00241 inst_conditions = [[],[],[]]
00242 for time,condition in enumerate(self.condition):
00243 try:
00244 condition.instantiate(var_mapping, init_facts, fluent_facts,
00245 init_function_vals, fluent_functions, task,
00246 new_axiom, new_modules, inst_conditions[time])
00247 except conditions.Impossible:
00248 return None
00249 effects = [[],[]]
00250 for time,timed_effects in enumerate(self.effects):
00251 for eff in timed_effects:
00252 eff.instantiate(var_mapping, init_facts, fluent_facts,
00253 init_function_vals, fluent_functions, task,
00254 new_axiom, new_modules, objects_by_type, effects[time])
00255 if effects:
00256 return PropositionalDurativeAction(name, inst_duration, inst_conditions, effects)
00257 else:
00258 return None
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269
00270
00271
00272
00273
00274
00275
00276
00277
00278
00279 class PropositionalAction:
00280 def __init__(self, name, precondition, effects):
00281 self.name = name
00282 self.condition = precondition
00283 self.add_effects = []
00284 self.del_effects = []
00285 self.assign_effects = []
00286 for (condition, effect) in effects:
00287 if isinstance(effect,f_expression.FunctionAssignment):
00288 self.assign_effects.append((condition, effect))
00289 elif effect.negated:
00290 self.del_effects.append((condition, effect.negate()))
00291 else:
00292 self.add_effects.append((condition, effect))
00293 def dump(self):
00294 print self.name
00295 for fact in self.condition:
00296 print "PRE: %s" % fact
00297 for cond, fact in self.add_effects:
00298 print "ADD: %s -> %s" % (", ".join(map(str, cond)), fact)
00299 for cond, fact in self.del_effects:
00300 print "DEL: %s -> %s" % (", ".join(map(str, cond)), fact)
00301 for cond, fact in self.assign_effects:
00302 print "ASS: %s -> %s" % (", ".join(map(str, cond)), fact)
00303
00304 class PropositionalDurativeAction:
00305 def __init__(self, name, duration, conditions, effects):
00306 self.name = name
00307 self.duration = duration
00308 self.conditions = conditions
00309 self.add_effects = [[],[]]
00310 self.del_effects = [[],[]]
00311 self.assign_effects = [[],[]]
00312 for time in range(2):
00313 for (condition, effect) in effects[time]:
00314 if isinstance(effect,f_expression.FunctionAssignment):
00315 self.assign_effects[time].append((condition, effect))
00316 elif effect.negated:
00317 self.del_effects[time].append((condition, effect.negate()))
00318 else:
00319 self.add_effects[time].append((condition, effect))
00320 def dump(self):
00321 print self.name
00322 for duration in self.duration[0]:
00323 print "START DUR: %s %s" % (duration[0],duration[1])
00324 for duration in self.duration[1]:
00325 print "END DUR: %s %s" % (duration[0],duration[1])
00326 for fact in self.conditions[0]:
00327 print "START COND: %s" % fact
00328 for fact in self.conditions[1]:
00329 print "OVER ALL COND: %s" % fact
00330 for fact in self.conditions[2]:
00331 print "END COND: %s" % fact
00332 for cond, fact in self.add_effects[0]:
00333 print "ADD START: %s -> %s" % (", ".join(map(str, cond)), fact)
00334 for cond, fact in self.add_effects[1]:
00335 print "ADD END: %s -> %s" % (", ".join(map(str, cond)), fact)
00336 for cond, fact in self.del_effects[0]:
00337 print "DEL START: %s -> %s" % (", ".join(map(str, cond)), fact)
00338 for cond, fact in self.del_effects[1]:
00339 print "DEL END: %s -> %s" % (", ".join(map(str, cond)), fact)
00340 for cond, fact in self.assign_effects[0]:
00341 print "ASS START: %s -> %s" % (", ".join(map(str, cond)), fact)
00342 for cond, fact in self.assign_effects[1]:
00343 print "ASS END: %s -> %s" % (", ".join(map(str, cond)), fact)