def add_inequality_preconds(self, action, reachable_action_params):
     if reachable_action_params is None or len(action.parameters) < 2:
         return action
     new_cond_parts = []
     combs = itertools.combinations(range(len(action.parameters)), 2)
     for pos1, pos2 in combs:
         for params in reachable_action_params[action.name]:
             if params[pos1] == params[pos2]:
                 break
         else:
             param1 = pddl.Variable(action.parameters[pos1].name)
             param2 = pddl.Variable(action.parameters[pos2].name)
             new_cond = pddl.NegatedAtom("=", (param1, param2))
             new_cond_parts.append(new_cond)
     if new_cond_parts:
         new_cond = list(action.condition)
         for time in (0, 2):  # add inequalities to start and end condition
             cond_parts = list(action.condition[time].parts)
             if isinstance(action.condition[time], pddl.Literal):
                 cond_parts = [action.condition[time]]
             cond_parts.extend(new_cond_parts)
             cond = pddl.Conjunction(cond_parts)
             new_cond[time] = cond
         return pddl.DurativeAction(action.name, action.parameters,
                                    action.grounding_call, action.duration,
                                    new_cond, action.effects)
     else:
         return action
Beispiel #2
0
def add_either_rules(type, rules):
    if isinstance(type, tuple):
        assert type[0] == "either"
        for subtype in type[1:]:
            add_either_rules(subtype, rules)
            rule_head = pddl.Atom(type, [pddl.Variable("?x")])
            rule_body = [pddl.Atom(subtype, [pddl.Variable("?x")])]
            rules.append((rule_body, rule_head))
Beispiel #3
0
def get_axiom_predicate(axiom):
    name = axiom
    variables = [pddl.Variable(par.name) for par in axiom.parameters]
    if isinstance(axiom.condition, pddl.ExistentialCondition):
        variables += [
            pddl.Variable(par.name) for par in axiom.condition.parameters
        ]
    return pddl.Atom(name, variables)
Beispiel #4
0
def get_action_predicate(action):
  name = action
  variables = [pddl.Variable(par.name) for par in action.parameters]
  if isinstance(action.condition,list):
    for condition in action.condition:
      if isinstance(condition, pddl.ExistentialCondition):
        variables += [pddl.Variable(par.name) for par in condition.parameters]
  if isinstance(action.condition, pddl.ExistentialCondition):
    variables += [pddl.Variable(par.name) for par in action.condition.parameters]
  return pddl.Atom(name, variables)
Beispiel #5
0
 def build_rules(self, rules, fluent_preds):
   axiom = self.owner
   app_rule_head = get_axiom_predicate(axiom)
   app_rule_body = list(condition_to_rule_body(axiom.parameters, self.condition))
   rules.append((app_rule_body, app_rule_head))
   eff_rule_head = pddl.Atom(axiom.name, [pddl.Variable(par.name) for par in axiom.parameters])
   eff_rule_body = [app_rule_head]
   rules.append((eff_rule_body, eff_rule_head))
Beispiel #6
0
    def build_rules(self, rules, fluent_preds, modules):
        effect = self.owner
        rule_head = effect.peffect
        # FIXME ModuleCalls do not have any effect (for now)
        # possibly add the affected fluents here?
        fluent_head = None
        module_heads = []
        if not isinstance(rule_head, pddl.NegatedAtom):
            if isinstance(rule_head, pddl.ModuleCall):
                # Determine the fluents this module sets
                my_module = None
                for module in modules:
                    if module.name == rule_head.name:
                        my_module = module
                        break
                if my_module:
                    # we need to rename all args, s.th. the module effect's
                    # fluents args are the same as in the modulecall.
                    assert len(my_module.parameters) == len(rule_head.args)
                    renamings = {}
                    for param, arg in zip(my_module.parameters,
                                          rule_head.args):
                        pVar = pddl.Variable(param.name)
                        renamings[pVar] = arg
                    # and add a function and fluent predicate for each
                    for fluent in my_module.effects:
                        new_fluent = fluent.rename_variables(renamings)
                        module_heads.append(get_function_predicate(new_fluent))
                        module_heads.append(
                            get_fluent_function_predicate(new_fluent))

                # finally disable the original single head.
                rule_head = None
            elif isinstance(rule_head, pddl.FunctionAssignment):
                fluent = rule_head.fluent
                rule_head = get_function_predicate(fluent)
                fluent_head = get_fluent_function_predicate(fluent)
            rule_body = [get_action_predicate(self.action)]
            if self.effecttime != None:
                # we use the start condition in any case
                rule_body += condition_to_rule_body([], self.condition[0])
                # for end effects we use all conditions
                if self.effecttime == 1:
                    rule_body += condition_to_rule_body([], self.condition[1])
                    rule_body += condition_to_rule_body([], self.condition[2])
            else:
                rule_body += condition_to_rule_body([], self.condition)
            if rule_head:
                rules.append((rule_body, rule_head))
            if fluent_head:
                rules.append((rule_body, fluent_head))
            for head in module_heads:
                rules.append((rule_body, head))
Beispiel #7
0
def condition_to_rule_body(parameters, condition, fluent_preds = None):
  for par in parameters:
    yield pddl.Atom(par.type, [pddl.Variable(par.name)])
  if not isinstance(condition, pddl.Truth):
    if isinstance(condition, pddl.ExistentialCondition):
      for par in condition.parameters:
        yield pddl.Atom(par.type, [pddl.Variable(par.name)])
      condition = condition.parts[0]
    if isinstance(condition, pddl.Conjunction):
      parts = condition.parts
    else:
      parts = (condition,)
    for part in parts:
      assert isinstance(part, pddl.Literal) or isinstance(part,pddl.FunctionComparison), "Condition not normalized"
      if isinstance(part, pddl.Literal):
        if not part.negated:
            if fluent_preds == None or part.predicate not in fluent_preds:
                yield part
      elif fluent_preds == None: # part is FunctionComparison
        primitives = part.primitive_numeric_expressions()
        for pne in primitives:
            yield get_function_predicate(pne)
Beispiel #8
0
 def _rename_duplicate_variables(self, atom, new_conditions):
     used_variables = set()
     new_args = list(atom.args)
     for i, var in enumerate(atom.args):
         if isinstance(var, pddl.Variable):
             if var in used_variables:
                 new_var_name = "%s@%d" % (var.name, len(new_conditions))
                 new_var = pddl.Variable(new_var_name)
                 new_args[i] = new_var
                 new_conditions.append(pddl.Atom("=", [var, new_var]))
             else:
                 used_variables.add(var)
     atom.args = tuple(new_args)
Beispiel #9
0
def condition_to_rule_body(parameters, condition, fluent_preds=None):
    for par in parameters:
        yield pddl.Atom(par.type, [pddl.Variable(par.name)])
    if not isinstance(condition, pddl.Truth):
        if isinstance(condition, pddl.ExistentialCondition):
            for par in condition.parameters:
                yield pddl.Atom(par.type, [pddl.Variable(par.name)])
            condition = condition.parts[0]
        if isinstance(condition, pddl.Conjunction):
            parts = condition.parts
        else:
            parts = (condition, )
        for part in parts:
            # FIXME Modulecall might be at lowest level
            assert isinstance(part, pddl.Literal) or isinstance(
                part, pddl.FunctionComparison) or isinstance(
                    part, pddl.ModuleCall), "Condition not normalized"
            if isinstance(part, pddl.Literal):
                if not part.negated:
                    if fluent_preds == None or part.predicate not in fluent_preds:
                        yield part
            elif isinstance(part, pddl.ModuleCall):
                # FIXME: yield nothing for that?
                # FIXME: this might be wrong - need to check, if rules are used
                # to build the task, then we would remove this wrongly
                # BUT this should be equivalent to TRUTH in the rule body
                # Alternativ: Make one of these "Atoms" (being true and holding module as "owner")
                # howevery they are used...
                # I guess we might wanna yield a truth "ModuleAtom" here...
                # or CAN WE IGNORE THIS?
                # there are also only non-negated literals in here...
                pass
            elif fluent_preds == None:  # part is FunctionComparison
                primitives = part.primitive_numeric_expressions()
                for pne in primitives:
                    yield get_function_predicate(pne)
Beispiel #10
0
def find_unique_variables(action, invariant):
    # find unique names for invariant variables
    params = set([p.name for p in action.parameters])
    for eff in action.effects[0]:
        params.update([p.name for p in eff.parameters])
    for eff in action.effects[1]:
        params.update([p.name for p in eff.parameters])
    inv_vars = []
    counter = itertools.count()
    for _ in xrange(invariant.arity()):
        while True:
            new_name = "?v%i" % counter.next()
            if new_name not in params:
                inv_vars.append(pddl.Variable(new_name))
                break
    return inv_vars
Beispiel #11
0
def remove_object_functions_from_durations(task):
    for act in task.durative_actions:
        used_variables = [var.name for var in act.parameters]
        for time in range(2):
            for index, (op, exp) in enumerate(act.duration[time]):
                typed_vars, function_terms, new_term = \
                    exp.compile_objectfunctions_aux(used_variables,
                                                    recurse_object_terms=False)
                act.duration[time][index] = (op, new_term)
                act.parameters += typed_vars
                new_conditions = []
                assert len(typed_vars) == len(function_terms)
                new_conditions = [act.condition[time]]
                for var, term in zip(typed_vars, function_terms):
                    variable = pddl.Variable(var.name)
                    new_condition = pddl.Atom("=", [variable, term])
                    new_conditions.append(new_condition)
                act.condition[time] = pddl.Conjunction(new_conditions)
Beispiel #12
0
def instantiate(task, model):
  relaxed_reachable = False
  fluent_facts = get_fluent_facts(task, model)
  fluent_functions = get_fluent_functions(model)

  ## HACK: This is a not very clean way of initializing the previously
  ## added functions that store the duration of an action to a haphazardly value
  for atom in model:
  	if isinstance(atom.predicate,str) and atom.predicate.startswith("defined!duration_"):
		pne = pddl.PrimitiveNumericExpression(atom.predicate.replace("defined!","",1),atom.args)
		value = pddl.NumericConstant(1.0)
		init_assign = pddl.Assign(pne, value)
		task.init.append(init_assign)

  init_facts = set(task.init) # TODO adapt
  init_function_vals = init_function_values(init_facts)

#  print "** fluent functions"
#  for function in fluent_functions:
#    function.dump()
#  print "** fluent facts"
#  for fact in fluent_facts:
#    print fact
#  print "** init facts"
#  for fact in init_facts:
#    print fact

  type_to_objects = get_objects_by_type(task.objects,task.types)

  instantiated_actions = []
  instantiated_durative_actions = []
  instantiated_axioms = []
  instantiated_numeric_axioms = set()
  new_constant_numeric_axioms = set()
  reachable_action_parameters = defaultdict(list)
  for atom in model:
    if isinstance(atom.predicate, pddl.Action):
      action = atom.predicate
      parameters = action.parameters
      if isinstance(action.condition, pddl.ExistentialCondition):
        parameters = list(parameters)
        parameters += action.condition.parameters
      variable_mapping = dict([(pddl.Variable(par.name), arg)
                               for par, arg in zip(parameters, atom.args)])
      inst_action = action.instantiate(variable_mapping, init_facts,
                                       fluent_facts, init_function_vals, fluent_functions,
                                       task, new_constant_numeric_axioms, type_to_objects)
      if inst_action:
        instantiated_actions.append(inst_action)
    elif isinstance(atom.predicate, pddl.DurativeAction):
      action = atom.predicate
      parameters = action.parameters
      reachable_action_parameters[action.name].append(parameters)
      for condition in action.condition:
        if isinstance(condition,pddl.ExistentialCondition):
          parameters = list(parameters)
          parameters += condition.parameters
      variable_mapping = dict([(pddl.Variable(par.name), arg)
                               for par, arg in zip(parameters, atom.args)])
      inst_action = action.instantiate(variable_mapping, init_facts, fluent_facts,
                                       init_function_vals, fluent_functions,
                                       task, new_constant_numeric_axioms, type_to_objects)
      if inst_action:
        instantiated_durative_actions.append(inst_action)
    elif isinstance(atom.predicate, pddl.Axiom):
      axiom = atom.predicate
      parameters = axiom.parameters
      if isinstance(axiom.condition, pddl.ExistentialCondition):
        parameters = list(parameters)
        parameters += axiom.condition.parameters
      variable_mapping = dict([(pddl.Variable(par.name), arg)
                               for par, arg in zip(parameters, atom.args)])
      inst_axiom = axiom.instantiate(variable_mapping, init_facts, fluent_facts,
                                     fluent_functions, init_function_vals, task,
                                     new_constant_numeric_axioms)
      if inst_axiom:
        instantiated_axioms.append(inst_axiom)
    elif isinstance(atom.predicate, pddl.NumericAxiom):
      axiom = atom.predicate
      variable_mapping = dict([(pddl.Variable(par.name), arg)
                               for par, arg in zip(axiom.parameters, atom.args)])
      new_constant_numeric_axioms = set()
      inst_axiom = axiom.instantiate(variable_mapping, fluent_functions, init_function_vals, 
                                     task, new_constant_numeric_axioms)
      instantiated_numeric_axioms.add(inst_axiom)
    elif atom.predicate == "@goal-reachable":
      relaxed_reachable = True
    instantiated_numeric_axioms |= new_constant_numeric_axioms
      
  return (relaxed_reachable, fluent_facts, fluent_functions, instantiated_actions, 
          instantiated_durative_actions, instantiated_axioms,
          instantiated_numeric_axioms, reachable_action_parameters)
Beispiel #13
0
def instantiate(task, model):
    relaxed_reachable = False
    fluent_facts = get_fluent_facts(task, model)
    fluent_functions = get_fluent_functions(model)

    ## HACK: This is a not very clean way of initializing the previously
    ## added functions that store the duration of an action to a haphazardly value
    for atom in model:
        if isinstance(atom.predicate,
                      str) and atom.predicate.startswith("defined!duration_"):
            pne = pddl.PrimitiveNumericExpression(
                atom.predicate.replace("defined!", "", 1), atom.args)
            value = pddl.NumericConstant(1.0)
            init_assign = pddl.Assign(pne, value)
            task.init.append(init_assign)

    init_facts = set(task.init)  # TODO adapt
    init_function_vals = init_function_values(init_facts)

    # Determine initial facts, that are not fluents => constant facts, that a module might need
    init_constant_fluents = set(init_function_vals)
    init_constant_fluents.difference_update(
        fluent_functions
    )  # all fluents that are in init, but are NOT a fluent -> constant

    # Now get the assigned values from the init_facts for the constant fluents
    init_constant_numeric_facts = set(
    )  # This will hold Assigns that assign the fluents
    for i in init_constant_fluents:
        for j in init_facts:
            if isinstance(j, pddl.Assign):
                if isinstance(j.fluent, pddl.PrimitiveNumericExpression):
                    if j.fluent is i:  # Assign in init_fact assign this (i) fluent
                        init_constant_numeric_facts.add(j)

    # Now get predicates that are in init, but are not fluent_facts
    init_constant_predicate_facts = set()
    for i in init_facts:
        if isinstance(i, pddl.Atom):  # do NOT consider PNEs, etc.
            if i not in fluent_facts:  # only consider non-fluents
                if i.predicate is not "=":  # hack to remove the intermediate '=' fluents
                    init_constant_predicate_facts.add(i)


#  print "** fluent functions"
#  for function in fluent_functions:
#    function.dump()
#  print "** fluent facts"
#  for fact in fluent_facts:
#    print fact
#  print "** init facts"
#  for fact in init_facts:
#    print fact

    type_to_objects = get_objects_by_type(task.objects, task.types)

    instantiated_actions = []
    instantiated_durative_actions = []
    instantiated_axioms = []
    instantiated_numeric_axioms = set()
    new_constant_numeric_axioms = set()
    reachable_action_parameters = defaultdict(list)
    instantiated_modules = set()
    for atom in model:
        if isinstance(atom.predicate, pddl.Action):
            action = atom.predicate
            parameters = action.parameters
            if isinstance(action.condition, pddl.ExistentialCondition):
                parameters = list(parameters)
                parameters += action.condition.parameters
            variable_mapping = dict([
                (pddl.Variable(par.name), arg)
                for par, arg in zip(parameters, atom.args)
            ])
            inst_action = action.instantiate(variable_mapping, init_facts,
                                             fluent_facts, init_function_vals,
                                             fluent_functions, task,
                                             new_constant_numeric_axioms,
                                             instantiated_modules,
                                             type_to_objects)
            if inst_action:
                instantiated_actions.append(inst_action)
        elif isinstance(atom.predicate, pddl.DurativeAction):
            action = atom.predicate
            parameters = action.parameters
            reachable_action_parameters[action.name].append(parameters)
            for condition in action.condition:
                if isinstance(condition, pddl.ExistentialCondition):
                    parameters = list(parameters)
                    parameters += condition.parameters
            variable_mapping = dict([
                (pddl.Variable(par.name), arg)
                for par, arg in zip(parameters, atom.args)
            ])
            inst_action = action.instantiate(variable_mapping, init_facts,
                                             fluent_facts, init_function_vals,
                                             fluent_functions, task,
                                             new_constant_numeric_axioms,
                                             instantiated_modules,
                                             type_to_objects)
            if inst_action:
                instantiated_durative_actions.append(inst_action)
        elif isinstance(atom.predicate, pddl.Axiom):
            axiom = atom.predicate
            parameters = axiom.parameters
            if isinstance(axiom.condition, pddl.ExistentialCondition):
                parameters = list(parameters)
                parameters += axiom.condition.parameters
            variable_mapping = dict([
                (pddl.Variable(par.name), arg)
                for par, arg in zip(parameters, atom.args)
            ])
            inst_axiom = axiom.instantiate(variable_mapping, init_facts,
                                           fluent_facts, fluent_functions,
                                           init_function_vals, task,
                                           new_constant_numeric_axioms,
                                           instantiated_modules)
            if inst_axiom:
                instantiated_axioms.append(inst_axiom)
        elif isinstance(atom.predicate, pddl.NumericAxiom):
            axiom = atom.predicate
            variable_mapping = dict([
                (pddl.Variable(par.name), arg)
                for par, arg in zip(axiom.parameters, atom.args)
            ])
            new_constant_numeric_axioms = set()
            inst_axiom = axiom.instantiate(variable_mapping, fluent_functions,
                                           init_function_vals, task,
                                           new_constant_numeric_axioms)
            instantiated_numeric_axioms.add(inst_axiom)
        elif atom.predicate == "@goal-reachable":
            relaxed_reachable = True
        instantiated_numeric_axioms |= new_constant_numeric_axioms

    return (relaxed_reachable, fluent_facts, fluent_functions,
            instantiated_actions, instantiated_durative_actions,
            instantiated_axioms, instantiated_numeric_axioms,
            instantiated_modules, init_constant_predicate_facts,
            init_constant_numeric_facts, reachable_action_parameters)