tasks.py
Go to the documentation of this file.
00001 import itertools
00002 
00003 import actions
00004 import axioms
00005 import conditions
00006 import effects
00007 import f_expression
00008 import functions
00009 import modules
00010 import predicates
00011 import pddl_types
00012 
00013 
00014 class Task(object):
00015   FUNCTION_SYMBOLS = dict()
00016   CONSTANT_MAPPING = dict() # yes, this is a hack and should be removed
00017 
00018   def __init__(self, domain_name, task_name, requirements, oplinit,
00019                types, objects, modules, predicates, init, goal, actions, durative_actions, axioms, function_symbols, subplan_generators, module_inits):
00020     self.domain_name = domain_name
00021     self.task_name = task_name
00022     self.requirements = requirements
00023     self.oplinit = oplinit
00024     self.types = types
00025     self.objects = objects
00026     self.modules = modules
00027     self.predicates = predicates
00028     self.init = init
00029     self.goal = goal
00030     self.actions = actions
00031     self.durative_actions = durative_actions
00032     self.axioms = axioms
00033     self.axiom_counter = 0
00034     self.function_symbols = function_symbols
00035     self.function_administrator = DerivedFunctionAdministrator()
00036     self.subplan_generators = subplan_generators
00037     self.module_inits = module_inits
00038 
00039   def add_axiom(self, parameters, condition):
00040     name = "new-axiom@%d" % self.axiom_counter
00041     self.axiom_counter += 1
00042     axiom = axioms.Axiom(name, parameters, condition)
00043     self.predicates.append(predicates.Predicate(name, parameters))
00044     self.axioms.append(axiom)
00045     return axiom
00046 
00047   def parse(domain_pddl, task_pddl):
00048     domain_name, requirements, oplinit, constants, predicates, types, functions, actions, durative_actions, axioms, modules, subplan_generators \
00049                  = parse_domain(domain_pddl)
00050     task_name, task_domain_name, module_inits, objects, init, goal = parse_task(task_pddl)
00051 
00052     assert domain_name == task_domain_name
00053     objects = constants + objects
00054     init += [conditions.Atom("=", (conditions.parse_term(obj.name), conditions.parse_term(obj.name))) 
00055              for obj in objects]
00056     return Task(domain_name, task_name, requirements, oplinit, types, objects, modules,
00057                 predicates, init, goal, actions, durative_actions, axioms, Task.FUNCTION_SYMBOLS, subplan_generators, module_inits)
00058   parse = staticmethod(parse)
00059 
00060   def dump(self):
00061     print "Problem %s: %s [%s]" % (self.domain_name, self.task_name,
00062                                    self.requirements)
00063     print "OplInit:"
00064     for init in self.oplinit:
00065       init.dump()
00066     print "Types:"
00067     for type in self.types:
00068       print "  %s" % type
00069     print "Objects:"
00070     for obj in self.objects:
00071       print "  %s" % obj
00072     print "Modules:"
00073     for module in self.modules:
00074       module.dump()
00075     print "Module Inits:"
00076     for mod_init in self.module_inits:
00077       mod_init.dump()
00078     print "Subplan Generators:"
00079     for spg in self.subplan_generators:
00080       spg.dump()
00081     print "Predicates:"
00082     for pred in self.predicates:
00083       print "  %s" % pred
00084     print "Functions:"
00085     print "  " + str(self.function_symbols)
00086     print "Init:"
00087     for fact in self.init:
00088       fact.dump()
00089     print "Goal:"
00090     self.goal.dump()
00091     print "Derived Functions:"
00092     self.function_administrator.dump()
00093     if self.actions:
00094         print "Actions:"
00095         for action in self.actions:
00096             action.dump()
00097     if self.durative_actions:
00098         print "Durative Actions:"
00099         for action in self.durative_actions:
00100             action.dump()
00101     if self.axioms:
00102       print "Axioms:"
00103       for axiom in self.axioms:
00104         axiom.dump()
00105 
00106 class Requirements(object):
00107   def __init__(self, requirements):
00108     self.requirements = requirements
00109     for req in requirements:
00110       assert req in (
00111         ":strips", ":adl", ":typing", ":negation", ":equality",
00112         ":negative-preconditions", ":disjunctive-preconditions",
00113         ":existential-preconditions", ":universal-preconditions",
00114         ":quantified-preconditions", ":conditional-effects",
00115         ":fluents", ":object-fluents", ":numeric-fluents", ":action-costs",
00116         ":durative-actions", ":derived-predicates", ":duration-inequalities", ":modules"), req
00117   def __str__(self):
00118     return ", ".join(self.requirements)
00119 
00120 class DerivedFunctionAdministrator(object):
00121     #TODO use hash values?
00122     def __init__(self):
00123         self.functions = dict()
00124 
00125     def dump(self,indent = "  "):
00126         for axiom in self.functions.values():
00127             axiom.dump(indent)
00128     def get_all_axioms(self):
00129         return self.functions.values() 
00130     def get_derived_function(self,exp):
00131         def get_default_variables(nr):
00132             return [conditions.Variable("?v%s" % varnr) for varnr in range(nr)]
00133         def get_new_symbol(key):   
00134             # introduce new derived function symbol
00135             used_names = [axiom.name for axiom in self.functions.values()]
00136             for counter in itertools.count(1):
00137                 new_func_name = "derived!" + str(counter)
00138                 if new_func_name not in used_names:
00139                     Task.FUNCTION_SYMBOLS[new_func_name]="number"
00140                     return new_func_name
00141 
00142         assert isinstance(exp,f_expression.FunctionalExpression)
00143         if isinstance(exp,f_expression.PrimitiveNumericExpression):
00144             return exp
00145         elif isinstance(exp,f_expression.NumericConstant):
00146             key = (exp.value,)
00147             if key not in self.functions:
00148                 symbol = get_new_symbol(key)
00149                 self.functions[key] = axioms.NumericAxiom(symbol,[],None,[exp])
00150             args = ()
00151         elif isinstance(exp,f_expression.AdditiveInverse):
00152             subexp = self.get_derived_function(exp.parts[0])
00153             key = (exp.op, subexp.symbol)
00154             args = subexp.args
00155             if key not in self.functions:
00156                 symbol = get_new_symbol(key)
00157                 default_args = get_default_variables(len(subexp.args)) 
00158                 subexp = f_expression.PrimitiveNumericExpression(subexp.symbol, default_args)
00159                 self.functions[key] = axioms.NumericAxiom(symbol, default_args, exp.op, [subexp])
00160         else:
00161             assert (isinstance(exp,f_expression.ArithmeticExpression) and
00162                     len(exp.parts) == 2)
00163             pne1 = self.get_derived_function(exp.parts[0])
00164             pne2 = self.get_derived_function(exp.parts[1])
00165             key = (exp.op, pne1.symbol, pne2.symbol)
00166             args = pne1.args + pne2.args
00167             if key not in self.functions:
00168                 if exp.op in ("+","*"):
00169                     key = (exp.op, pne2.symbol, pne1.symbol)
00170                     pne1,pne2 = pne2,pne1
00171                     args = pne1.args + pne2.args
00172                 if key not in self.functions:
00173                     symbol = get_new_symbol(key)
00174                     default_args = get_default_variables(len(args))
00175                     pne1 = f_expression.PrimitiveNumericExpression(pne1.symbol, 
00176                                                 default_args[:len(pne1.args)])
00177                     if pne2.args:
00178                         pne2 = f_expression.PrimitiveNumericExpression(pne2.symbol, 
00179                                                 default_args[-len(pne2.args):])
00180                     
00181                     self.functions[key] = axioms.NumericAxiom(symbol, tuple(default_args),
00182                                                               exp.op,[pne1,pne2]) 
00183         pne_symbol = self.functions[key].get_head().symbol
00184         return f_expression.PrimitiveNumericExpression(pne_symbol,args)
00185 
00186 def parse_domain_structure(entry,the_functions,the_axioms,the_actions,the_durative_actions, 
00187                            the_types, the_predicates):
00188     if entry[0] == ":derived":
00189       axiom = axioms.Axiom.parse(entry)
00190       the_axioms.append(axiom)
00191     elif entry[0] == ":durative-action":
00192       action = actions.DurativeAction.parse(entry)
00193       the_durative_actions.append(action)
00194     elif entry[0] == ":functions":
00195       the_functions.extend(pddl_types.parse_typed_list(entry[1:], 
00196         constructor=functions.Function.parse_typed, functions=True, types=the_types))
00197       for function in the_functions:
00198         Task.FUNCTION_SYMBOLS[function.name] = function.type
00199         if function.type != "number":
00200             the_predicates.append(
00201                 predicates.Predicate(conditions.function_predicate_name(function.name),
00202                                      function.arguments + [pddl_types.TypedObject("?val", function.type)]))
00203     elif entry[0] == ":action":
00204       action = actions.Action.parse(entry)
00205       the_actions.append(action)
00206     else:
00207       assert False, "unknown entity"
00208 
00209 def parse_domain(domain_pddl):
00210   iterator = iter(domain_pddl)
00211   
00212   the_functions = []
00213   the_axioms = []
00214   the_actions = []
00215   the_durative_actions = []
00216   the_modules = []
00217   the_subplan_generators = []
00218 
00219   assert iterator.next() == "define"
00220   domain_line = iterator.next()
00221   assert domain_line[0] == "domain" and len(domain_line) == 2
00222   yield domain_line[1]
00223 
00224   opt_requirements = iterator.next()
00225   if opt_requirements[0] == ":requirements":
00226     yield Requirements(opt_requirements[1:])
00227     oplinit = iterator.next()
00228   else:
00229     yield Requirements([":strips"])
00230     oplinit = opt_requirements
00231 
00232   if oplinit[0] == ":oplinit":
00233     yield [modules.OplInit.parse(mi) for mi in oplinit[1:]]
00234     opt_types = iterator.next()
00235   else:
00236     yield []  
00237     opt_types = oplinit  
00238 
00239   the_types = [pddl_types.Type("object")]
00240   if opt_types[0] == ":types":
00241     the_types.extend(pddl_types.parse_typed_list(opt_types[1:],
00242                                                  constructor=pddl_types.Type))
00243     opt_modules = iterator.next()
00244   else:
00245     opt_modules = opt_types
00246 
00247   if opt_modules[0] == ":modules":
00248     for mod_entry in opt_modules[1:]:
00249       if mod_entry[0] == "subplan_generator":
00250         the_subplan_generators.append(modules.SubplanGenerator.parse(mod_entry))
00251       else:
00252         the_modules.append(modules.Module.parse(mod_entry))
00253     opt_constants = iterator.next()
00254   else:
00255     opt_constants = opt_modules
00256 
00257   if opt_constants[0] == ":constants":
00258     yield pddl_types.parse_typed_list(opt_constants[1:],types=the_types)
00259     pred = iterator.next()
00260   else:
00261     yield []
00262     pred = opt_constants
00263 
00264   the_predicates = []
00265   if pred[0] == ":predicates":
00266     the_predicates =  ([predicates.Predicate.parse(entry) for entry in pred[1:]] +
00267          [predicates.Predicate("=",
00268                                [pddl_types.TypedObject("?x", "object"),
00269                                 pddl_types.TypedObject("?y", "object")])])
00270   else:
00271     the_predicates = [predicates.Predicate("=",
00272                                 [pddl_types.TypedObject("?x", "object"),
00273                                  pddl_types.TypedObject("?y", "object")])]
00274     parse_domain_structure(pred,the_functions,the_axioms,the_actions,the_durative_actions,the_types,the_predicates)
00275 
00276   for entry in iterator:
00277     parse_domain_structure(entry,the_functions,the_axioms,the_actions,the_durative_actions,the_types,the_predicates)
00278 
00279   pddl_types.set_supertypes(the_types)
00280   the_types = [type for type in the_types if type.supertype_names != [] or type.name == "object"]
00281   yield the_predicates
00282   yield the_types
00283   yield the_functions
00284   yield the_actions
00285   yield the_durative_actions
00286   yield the_axioms
00287   yield the_modules
00288   yield the_subplan_generators
00289 
00290 def parse_task(task_pddl):
00291   iterator = iter(task_pddl)
00292 
00293   assert iterator.next() == "define"
00294   problem_line = iterator.next()
00295   assert problem_line[0] == "problem" and len(problem_line) == 2
00296   yield problem_line[1]
00297   domain_line = iterator.next()
00298   assert domain_line[0] == ":domain" and len(domain_line) == 2
00299   yield domain_line[1]
00300 
00301   module_opt = iterator.next()
00302   if module_opt[0] == ":moduleoptions":
00303     yield [modules.ModuleInit.parse(mi) for mi in module_opt[1:]]
00304     objects_opt = iterator.next()
00305   else:
00306     yield []
00307     objects_opt = module_opt
00308   
00309   if objects_opt[0] == ":objects":
00310     yield pddl_types.parse_typed_list(objects_opt[1:])
00311     init = iterator.next()
00312   else:
00313     yield []
00314     init = objects_opt
00315 
00316   assert init[0] == ":init"
00317   initial = []
00318   for fact in init[1:]:
00319     if fact[0] == "=":
00320         if conditions.is_function_comparison(fact): # numeric function
00321             initial.append(f_expression.parse_assignment(fact))
00322         else: # object function
00323             function = conditions.parse_term(fact[1])
00324             terms = function.args
00325             terms.append(conditions.parse_term(fact[2]))
00326             atomname = conditions.function_predicate_name(function.name)
00327             initial.append(conditions.Atom(atomname, terms))
00328     else:
00329         initial.append(conditions.Atom(fact[0], [conditions.parse_term(term) for term in fact[1:]]))
00330   yield initial
00331 
00332   goal = iterator.next()
00333   assert goal[0] == ":goal" and len(goal) == 2
00334   yield conditions.parse_condition(goal[1])
00335 
00336   for entry in iterator:
00337     if entry[0] == ":metric" and entry[1]=="minimize":
00338         if entry[2][0] in ["total-time", "total-cost"] :
00339             continue
00340     assert False, "Can only minimize total-time or total-cost, got: " + str(entry)
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines


tfd_modules
Author(s): Maintained by Christian Dornhege (see AUTHORS file).
autogenerated on Tue Jan 22 2013 12:25:03