Ejemplo n.º 1
0
def translate_strips_conditions_aux(conditions,
                                    dictionary,
                                    ranges,
                                    numeric_dictionary,
                                    comparison_axioms,
                                    mutex_check=False):
    condition = {}
    comp_axiom_dict = comparison_axioms[0]
    sas_comp_axioms = comparison_axioms[1]
    for fact in conditions:
        if (isinstance(fact, pddl.FunctionComparison)
                or isinstance(fact, pddl.NegatedFunctionComparison)):
            #            print("comparison condition in translate strips condition aux:")
            if fact not in dictionary:
                #                print("Fact is not in dictionary")
                for part in fact.parts:  # TODO: remove this assertion check when not debugging
                    assert part in numeric_dictionary
                parts = [numeric_dictionary[part] for part in fact.parts]
                key = (fact.comparator, tuple(parts))
                negated = fact.negated
                if key in comp_axiom_dict:
                    #                    print("key %s ist im comp_axiom_dict" % [key])
                    #                    print(comp_axiom_dict)
                    fact = comp_axiom_dict[key]
                    if negated:
                        #                       print("(nach dem negieren)")
                        fact = fact.negate()
                else:
                    axiom = sas_tasks.SASCompareAxiom(fact.comparator, parts,
                                                      len(ranges))
                    if negated:
                        negfact = fact
                        posfact = fact.negate()
                    else:
                        posfact = fact
                        negfact = fact.negate()

                    if not mutex_check:  # if mutexes are checked the axioms will not be added because the
                        # strips to sas dictionary would not be updated properly otherwise
                        sas_comp_axioms.append(axiom)
                        comp_axiom_dict[key] = posfact
                    dictionary.setdefault(posfact, []).append((len(ranges), 0))
                    dictionary.setdefault(negfact, []).append((len(ranges), 1))
                    ranges.append(3)


#            print (dictionary[fact])
            var, val = dictionary[fact][0]
            if (var in condition and val not in condition[var]):
                # Conflicting conditions on this variable: Operator invalid.
                return None
            condition[var] = set([val])
        else:
            if fact.negated:
                # we handle negative conditions later, because then we
                # can recognize when the negative condition is already
                # ensured by a positive condition
                continue
            for var, val in dictionary.get(fact, ()):
                # The default () here is a bit of a hack. For goals (but
                # only for goals!), we can get static facts here. They
                # cannot be statically false (that would have been
                # detected earlier), and hence they are statically true
                # and don't need to be translated.
                # TODO: This would not be necessary if we dealt with goals
                # in the same way we deal with operator preconditions etc.,
                # where static facts disappear during grounding. So change
                # this when the goal code is refactored (also below). (**)
                if (condition.get(var) is not None
                        and val not in condition.get(var)):
                    # Conflicting conditions on this variable: Operator invalid.
                    return None
                condition[var] = set([val])

    def number_of_values(var_vals_pair):
        var, vals = var_vals_pair
        return len(vals)

    for fact in conditions:
        if (isinstance(fact, pddl.FunctionComparison)
                or isinstance(fact, pddl.NegatedFunctionComparison)):
            continue
        if fact.negated:
            ## Note  Here we use a different solution than in Sec. 10.6.4
            ##       of the thesis. Compare the last sentences of the third
            ##       paragraph of the section.
            ##       We could do what is written there. As a test case,
            ##       consider Airport ADL tasks with only one airport, where
            ##       (occupied ?x) variables are encoded in a single variable,
            ##       and conditions like (not (occupied ?x)) do occur in
            ##       preconditions.
            ##       However, here we avoid introducing new derived predicates
            ##       by treat the negative precondition as a disjunctive
            ##       precondition and expanding it by "multiplying out" the
            ##       possibilities.  This can lead to an exponential blow-up so
            ##       it would be nice to choose the behaviour as an option.
            done = False
            new_condition = {}
            atom = pddl.Atom(fact.predicate, fact.args)  # force positive
            for var, val in dictionary.get(atom, ()):
                # see comment (**) above
                poss_vals = set(range(ranges[var]))
                poss_vals.remove(val)

                if condition.get(var) is None:
                    assert new_condition.get(var) is None
                    new_condition[var] = poss_vals
                else:
                    # constrain existing condition on var
                    prev_possible_vals = condition.get(var)
                    done = True
                    prev_possible_vals.intersection_update(poss_vals)
                    if len(prev_possible_vals) == 0:
                        # Conflicting conditions on this variable:
                        # Operator invalid.
                        return None

            if not done and len(new_condition) != 0:
                # we did not enforce the negative condition by constraining
                # an existing condition on one of the variables representing
                # this atom. So we need to introduce a new condition:
                # We can select any from new_condition and currently prefer the
                # smallest one.
                candidates = sorted(new_condition.items(),
                                    key=number_of_values)
                var, vals = candidates[0]
                condition[var] = vals

    def multiply_out(condition):  # destroys the input
        sorted_conds = sorted(condition.items(), key=number_of_values)
        flat_conds = [{}]
        for var, vals in sorted_conds:
            if len(vals) == 1:
                for cond in flat_conds:
                    cond[var] = vals.pop()  # destroys the input here
            else:
                new_conds = []
                for cond in flat_conds:
                    for val in vals:
                        new_cond = deepcopy(cond)
                        new_cond[var] = val
                        new_conds.append(new_cond)
                flat_conds = new_conds
        return flat_conds

    return multiply_out(condition)
Ejemplo n.º 2
0
def translate_strips_conditions_aux(conditions, dictionary, ranges):
    condition = {}
    for fact in conditions:
        if fact.negated:
            # we handle negative conditions later, because then we
            # can recognize when the negative condition is already
            # ensured by a positive condition
            continue
        for var, val in dictionary.get(fact, ()):
            # The default () here is a bit of a hack. For goals (but
            # only for goals!), we can get static facts here. They
            # cannot be statically false (that would have been
            # detected earlier), and hence they are statically true
            # and don't need to be translated.
            # TODO: This would not be necessary if we dealt with goals
            # in the same way we deal with operator preconditions etc.,
            # where static facts disappear during grounding. So change
            # this when the goal code is refactored (also below). (**)
            if (condition.get(var) is not None and
                val not in condition.get(var)):
                # Conflicting conditions on this variable: Operator invalid.
                return None
            condition[var] = set([val])

    for fact in conditions:
        if fact.negated:
           ## Note  Here we use a different solution than in Sec. 10.6.4
           ##       of the thesis. Compare the last sentences of the third
           ##       paragraph of the section.
           ##       We could do what is written there. As a test case,
           ##       consider Airport ADL tasks with only one airport, where
           ##       (occupied ?x) variables are encoded in a single variable,
           ##       and conditions like (not (occupied ?x)) do occur in
           ##       preconditions.
           ##       However, here we avoid introducing new derived predicates
           ##       by treat the negative precondition as a disjunctive precondition
           ##       and expanding it by "multiplying out" the possibilities.
           ##       This can lead to an exponential blow-up so it would be nice
           ##       to choose the behaviour as an option.
            done = False
            new_condition = {}
            atom = pddl.Atom(fact.predicate, fact.args) # force positive
            for var, val in dictionary.get(atom, ()):
                # see comment (**) above
                poss_vals = set(range(ranges[var]))
                poss_vals.remove(val)

                if condition.get(var) is None:
                    assert new_condition.get(var) is None
                    new_condition[var] = poss_vals
                else:
                    # constrain existing condition on var
                    prev_possible_vals = condition.get(var)
                    done = True
                    prev_possible_vals.intersection_update(poss_vals)
                    if len(prev_possible_vals) == 0:
                        # Conflicting conditions on this variable:
                        # Operator invalid.
                        return None

            if not done and len(new_condition) != 0:
                # we did not enforce the negative condition by constraining
                # an existing condition on one of the variables representing
                # this atom. So we need to introduce a new condition:
                # We can select any from new_condition and currently prefer the
                # smalles one.
                candidates = sorted(new_condition.items(),
                                    lambda x,y: cmp(len(x[1]),len(y[1])))
                var, vals = candidates[0]
                condition[var] = vals

        def multiply_out(condition): # destroys the input
            sorted_conds = sorted(condition.items(),
                                  lambda x,y: cmp(len(x[1]),len(y[1])))
            flat_conds = [{}]
            for var, vals in sorted_conds:
                if len(vals) == 1:
                    for cond in flat_conds:
                        cond[var] = vals.pop() # destroys the input here
                else:
                    new_conds = []
                    for cond in flat_conds:
                        for val in vals:
                            new_cond = deepcopy(cond)
                            new_cond[var] = val
                            new_conds.append(new_cond)
                    flat_conds = new_conds
            return flat_conds

    return multiply_out(condition)
Ejemplo n.º 3
0
def get_axiom_predicate(axiom):
  name = axiom
  variables = [par.name for par in axiom.parameters]
  if isinstance(axiom.condition, pddl.ExistentialCondition):
    variables += [par.name for par in axiom.condition.parameters]
  return pddl.Atom(name, variables)
Ejemplo n.º 4
0
 def add_rule(self, type, conditions, effect_vars):
     effect = pddl.Atom(self.name_generator.next(), effect_vars)
     rule = pddl_to_prolog.Rule(conditions, effect)
     rule.type = type
     self.result.append(rule)
     return rule.effect
Ejemplo n.º 5
0
 def push(self, predicate, args):
     self.num_pushes += 1
     eff_tuple = (predicate, ) + tuple(args)
     if eff_tuple not in self.enqueued:
         self.enqueued.add(eff_tuple)
         self.queue.append(pddl.Atom(predicate, list(args)))
Ejemplo n.º 6
0
 def build_rules(self, rules):
   rule_head_name = "@goal-reachable"
   rule_head = pddl.Atom("@goal-reachable", [])
   rule_body = list(condition_to_rule_body([], self.condition))
   rules.append((rule_body, rule_head))
Ejemplo n.º 7
0
def project_rule(rule, conditions, name_generator):
    predicate = next(name_generator)
    effect_variables = set(rule.effect.args) & get_variables(conditions)
    effect = pddl.Atom(predicate, sorted(effect_variables))
    projected_rule = Rule(conditions, effect)
    return projected_rule
Ejemplo n.º 8
0
 def instantiate(self, parameters):
     args = ["?X"] * (len(self.order) + (self.omitted_pos != -1))
     for arg, argpos in zip(parameters, self.order):
         args[argpos] = arg
     return pddl.Atom(self.predicate, args)
Ejemplo n.º 9
0
def test_normalization():
    prog = PrologProgram()
    prog.add_fact(pddl.Atom("at", ["foo", "bar"]))
    prog.add_fact(pddl.Atom("truck", ["bollerwagen"]))
    prog.add_fact(pddl.Atom("truck", ["segway"]))
    prog.add_rule(
        Rule([pddl.Atom("truck", ["?X"])], pddl.Atom("at", ["?X", "?Y"])))
    prog.add_rule(
        Rule([pddl.Atom("truck", ["X"]),
              pddl.Atom("location", ["?Y"])], pddl.Atom("at", ["?X", "?Y"])))
    prog.add_rule(
        Rule([pddl.Atom("truck", ["?X"]),
              pddl.Atom("location", ["?Y"])], pddl.Atom("at", ["?X", "?X"])))
    prog.add_rule(
        Rule([pddl.Atom("p", ["?Y", "?Z", "?Y", "?Z"])],
             pddl.Atom("q", ["?Y", "?Y"])))
    prog.add_rule(Rule([], pddl.Atom("foo", [])))
    prog.add_rule(Rule([], pddl.Atom("bar", ["X"])))
    prog.normalize()
    prog.dump()
Ejemplo n.º 10
0
def translate_typed_object(prog, obj, type_dict):
    supertypes = type_dict[obj.type].supertype_names
    for type_name in [obj.type] + supertypes:
        prog.add_fact(pddl.Atom(type_name, [obj.name]))
Ejemplo n.º 11
0
def parse_task_pddl(task_pddl, type_dict, predicate_dict):
    iterator = iter(task_pddl)

    define_tag = next(iterator)
    assert define_tag == "define"
    problem_line = next(iterator)
    assert problem_line[0] == "problem" and len(problem_line) == 2
    yield problem_line[1]
    domain_line = next(iterator)
    assert domain_line[0] == ":domain" and len(domain_line) == 2
    yield domain_line[1]

    requirements_opt = next(iterator)
    if requirements_opt[0] == ":requirements":
        requirements = requirements_opt[1:]
        objects_opt = next(iterator)
    else:
        requirements = []
        objects_opt = requirements_opt
    yield pddl.Requirements(requirements)

    if objects_opt[0] == ":objects":
        yield parse_typed_list(objects_opt[1:])
        init = next(iterator)
    else:
        yield []
        init = objects_opt

    assert init[0] == ":init"
    initial = []
    initial_true = set()
    initial_false = set()
    initial_assignments = dict()
    for fact in init[1:]:
        if fact[0] == "=":
            try:
                assignment = parse_assignment(fact)
            except ValueError as e:
                raise SystemExit("Error in initial state specification\n" +
                                 "Reason: %s." % e)
            if not isinstance(assignment.expression, pddl.NumericConstant):
                raise SystemExit("Illegal assignment in initial state " +
                                 "specification:\n%s" % assignment)
            if assignment.fluent in initial_assignments:
                prev = initial_assignments[assignment.fluent]
                if assignment.expression == prev.expression:
                    print("Warning: %s is specified twice" % assignment,
                          "in initial state specification")
                else:
                    raise SystemExit("Error in initial state specification\n" +
                                     "Reason: conflicting assignment for " +
                                     "%s." % assignment.fluent)
            else:
                initial_assignments[assignment.fluent] = assignment
                initial.append(assignment)
        elif fact[0] == "not":
            atom = pddl.Atom(fact[1][0], fact[1][1:])
            check_atom_consistency(atom, initial_false, initial_true, False)
            initial_false.add(atom)
        else:
            atom = pddl.Atom(fact[0], fact[1:])
            check_atom_consistency(atom, initial_true, initial_false)
            initial_true.add(atom)
    initial.extend(initial_true)
    yield initial

    goal = next(iterator)
    assert goal[0] == ":goal" and len(goal) == 2
    yield parse_condition(goal[1], type_dict, predicate_dict)

    use_metric = False
    for entry in iterator:
        if entry[0] == ":metric":
            if entry[1] == "minimize" and entry[2][0] == "total-cost":
                use_metric = True
            else:
                assert False, "Unknown metric."
    yield use_metric

    for entry in iterator:
        assert False, entry