Beispiel #1
0
    def _parse_problem(self, f_problem):
        """
        Extract information from the problem file.

        The following will be extracted:
            * problem name
            * objects
            * initial state
            * goal state
            * type_to_obj
            * obj_to_type
        """

        parse_tree = PDDL_Tree.create(f_problem)

        assert "problem" in parse_tree, "Problem must have a name"
        self.problem_name = parse_tree["problem"].named_children()[0]

        # objects must be parsed first
        if ":objects" in parse_tree:
            object_list = PDDL_Utils.read_type(parse_tree[":objects"])
            self._add_objects(object_list)

        #TODO this may not be valid with a non-flat type hierchy
        obj_map = {obj: list(self.obj_to_type[obj])[0] for obj in self.objects}

        # the goal can be expressed in either a formula form, or a direct form
        if len(parse_tree[":goal"].children
               ) == 1 and parse_tree[":goal"].children[0].name == "and":
            self.goal = And([
                Primitive(self.to_fluents(c))
                for c in parse_tree[":goal"].children[0].children
            ])
        else:
            self.goal = And([
                Primitive(self.to_fluents(c))
                for c in parse_tree[":goal"].children
            ])

        # it is critical that the formula here be checked against the objects
        if len(parse_tree[":init"].children) == 1 and \
                parse_tree[":init"].children[0].name == "and":
            self.init = self.to_formula(parse_tree[":init"].children[0],
                                        obj_map)
        else:
            # initial condition is one big AND
            #            print "```", self.init
            self.init = And([
                self.to_formula(c, obj_map)
                for c in parse_tree[":init"].children
            ])
Beispiel #2
0
 def __init__(self, p, h):
     self.problem = p
     self.initial = p.init
     # self.actions = p.actions
     self.goal = p.goal
     # self.type_to_obj = p.type_to_obj
     # self.objects = p.obj_to_type
     self.fluents = p.fluents
     self.operators = p.operators
     self.precs = {}
     self.effects = {}
     self.observes = {}
     self.adds_fluent = {}#use
     self.dels_fluent = {}#use
     self.horizon = h
     self.j = 1
     self.logic = Logic()
     self.jk = []
     self.fluent_lits = []
     self.op_lits = []
     self.djk_lits = []
     self.all_literals = []
     self.initial_lits = None
     self.subproblems = []
     self.init_known = None
     self.lit_dict = {}
     self.lit_lookup = {}
     self.dg_atom = Predicate('DG', None, [])
     self.fluents.add(self.dg_atom)
     self.end_atom = Operator('End', [], self.goal, None, And([Primitive(self.dg_atom)]))
     self.operators.add(self.end_atom)
Beispiel #3
0
def compile(problem, T, M, init_TL):
    """Returns new GroundProblem instance."""

    # verify inputs
    assert isinstance (problem, GroundProblem), \
        "The problem must be ground"
    assert isinstance(T, list) and \
        all([isinstance(t, Literal) for t in T]), \
        "Tags must be a list of Literals"
    assert isinstance(M, list) and \
        all([isinstance(m, tuple) for m in M]),\
        "Merges must be a list of tuples"
    assert isinstance(init_TL, list) and \
        all([isinstance(e, tuple) for e in init_TL]),\
        "Initial tag literals must be a list of tuples"

    fluents = []
    fluent_dict = {}
    conversion_dict = {}
    for fluent in problem.fluents:
        l_name = "K%s" % fluent.name
        kl = Predicate(l_name, None, fluent.ground_args)
        fluents.append(kl)
        fluent_dict[hash(kl)] = kl
        conversion_dict[hash(fluent)] = kl

        l_not_name = "K_not_%s" % fluent.name
        k_notl = Predicate(l_not_name, None, fluent.ground_args)
        fluents.append(k_notl)
        fluent_dict[hash(k_notl)] = k_notl

        for tag in T:
            l_name = "K_%s_|_%s" % (fluent.name, tag.name)
            kl = Predicate(l_name, None, fluent.ground_args)
            fluents.append(kl)
            fluent_dict[hash(kl)] = kl

            l_not_name = "K_not_%s_|_%s" % (fluent.name, tag.name)
            k_notl = Predicate(l_not_name, None, fluent.ground_args)
            fluents.append(k_notl)
            fluent_dict[hash(k_notl)] = k_notl

    print "* New fluents *"
    for fluent in fluents:
        print fluent

    #TODO new initial state

    print "* New goal state *"
    goal_fluents = []
    for arg in problem.goal.args:
        p = Primitive(conversion_dict[hash(arg.predicate)])
        goal_fluents.append(p)
        print p
Beispiel #4
0
    def _partial_ground_formula(self, formula, assignment, fluent_dict):
        """
        Inputs:
            formula            The formula to be converted
            assignment        a dictionary mapping each possible variable name to an object

        Returns:
            A formula that has the particular valuation for the variables as given in input. The old formula is *untouched*
        """

        if formula is None:
            return None

        if isinstance(formula, Primitive):
            new_prim = Primitive(self._predicate_to_fluent(formula.predicate, assignment, fluent_dict))
            new_prim.agent_list = formula.agent_list
            new_prim.negated_rml = formula.negated_rml
            for k in assignment:
                new_prim.agent_list = new_prim.agent_list.replace(k, assignment[k])
            return new_prim
        elif isinstance(formula, Forall):

            new_conjuncts = []
            var_names, val_generator = self._create_valuations(formula.params)
            for valuation in val_generator:
                new_assignment = {var_name: val for var_name, val in zip(var_names, valuation)}
                for k in assignment:
                    new_assignment[k] = assignment[k]
                new_conjuncts.append(self._partial_ground_formula(formula.args[0], new_assignment, fluent_dict))
            return And(new_conjuncts)

        elif isinstance(formula, When):
            return When(self._partial_ground_formula(formula.condition, assignment, fluent_dict),
                        self._partial_ground_formula(formula.result, assignment, fluent_dict))
        else:
            return type(formula)([self._partial_ground_formula(arg, assignment, fluent_dict) for arg in formula.args])
Beispiel #5
0
    def create_literals(self):

        self.all_atoms = list(self.fluents) + list(self.possible_ops) + self.jk
        for t in range(self.horizon):
            for j in range(self.j):
                for f in self.fluents:
                    lit = Literal('fluent', f, (j,t))
                    self.fluent_lits.append(lit)
                    self.lit_lookup[f, j, t] = lit
        for t in range(self.horizon-1):
            for j in range(self.j):
                for o in self.possible_ops:
                    lit = Literal('action', o, (j,t))
                    self.op_lits.append(lit)
                    self.lit_lookup[o, j, t] = lit
                    self.precs[lit] = self.lit_formula(o.precondition, j,t)
                    self.effects[lit] = self.lit_formula(o.effect, j, t+1)
                    self.observes[lit] = self.lit_formula(o.observe,j,t+1)
                    if o.name == 'End':
                        self.effects[lit] = And([ self.effects[lit], self.lit_formula(Primitive(self.dg_atom), j, self.horizon-1)])

        for t in range(self.horizon):
            for djk in self.jk:
                lit = Literal('D', djk, t)
                self.djk_lits.append(Literal('D', djk, t))
                self.lit_lookup['D',djk, t] = lit

        self.all_literals = self.fluent_lits + self.op_lits + self.djk_lits
        self.goal_lits = [self.lit_lookup[self.dg_atom, j, self.horizon-1] for j in range(self.j)]
        self.initial_lits = [self.lit_formula(self.init_known, j, 0) for j in range(self.j)]
        self.subinit_lits = [self.lit_formula(And(self.subproblems[j]),j, 0) for j in range(self.j)]
        self.initnot_lits = [self.lit_formula(And([Not([Primitive(i)])   for i in self.initnot]),j,0) for j in range(self.j)]

        d = 1
        for l in self.all_literals:
            self.lit_dict[l] = d
            d += 1
Beispiel #6
0
    def to_formula(self, node, parameter_map=None):
        """
            Return a formula out of this PDDL_Tree node.
            For now, will assume this makes sense.
        """

        # forall is so weird that we can treat it as an entirely seperate entity
        if "forall" == node.name:
            # treat args differently in this case
            assert len(node.children) in[2, 4],\
                "Forall must have a variable(typed or untyped) and formula that it quantifies"
            i = len(node.children) - 1

            if len(node.children) == 2 and len(node.children[0].children) > 0:
                # adjust this node by changing the structure of the first child
                new_child = PDDL_Tree(PDDL_Tree.EMPTY)
                new_child.add_child(PDDL_Tree(node.children[0].name))

                for c in node.children[0].children:
                    new_child.add_child(c)
                node.children[0] = new_child
                l = PDDL_Utils.read_type(new_child)

            for v, t in l:
                parameter_map[v] = t
            args = [
                self.to_formula(c, parameter_map) for c in node.children[i:]
            ]
            for v, t in l:
                del (parameter_map[v])
            return Forall(l, args)

        i = 0
        args = [self.to_formula(c, parameter_map) for c in node.children[i:]]

        if "and" == node.name:
            return And(args)
        elif "or" == node.name:
            return Or(args)
        elif "oneof" == node.name:
            return Oneof(args)
        elif "not" == node.name:
            return Not(args)
        elif "xor" == node.name:
            return Xor(args)
        elif "nondet" == node.name:
            assert len(node.children) == 1,\
                                       "nondet must only have a single child as a predicate"
            # make p != p2, otherwise might run into issues with mutation in some later step
            return Oneof([args[0], Not(args)])
        elif "unknown" == node.name:
            assert len(node.children) == 1,\
                "unknown must only have a single child as a predicate"
            # make p != p2, otherwise might run into issues with mutation in some later step
            p = Primitive(
                self.to_predicate(node.children[0], map=parameter_map))
            p2 = Primitive(
                self.to_predicate(node.children[0], map=parameter_map))
            return Xor([p, Not([p2])])
        elif "when" == node.name:
            assert len(args) == 2,\
                "When clause must have exactly 2 children"
            return When(args[0], args[1])
        else:
            # it's a predicate
            return Primitive(self.to_predicate(node, map=parameter_map))
Beispiel #7
0
    def to_formula(self, node, parameter_map=None):
        """
            Return a formula out of this PDDL_Tree node.
            For now, will assume this makes sense.
        """

        # forall is so weird that we can treat it as an entirely seperate entity
        if "forall" == node.name:
            # treat args differently in this case
            assert len(node.children) in[2, 4],\
                "Forall must have a variable(typed or untyped) and formula that it quantifies"
            i = len(node.children) - 1

            if len(node.children) == 2 and len(node.children[0].children) > 0:
                # adjust this node by changing the structure of the first child
                new_child = PDDL_Tree(PDDL_Tree.EMPTY)
                new_child.add_child(PDDL_Tree(node.children[0].name))

                for c in node.children[0].children:
                    new_child.add_child(c)
                node.children[0] = new_child
                l = PDDL_Utils.read_type(new_child)
            else:
                l = [(node.children[0].name, node.children[2].name)]

            for v, t in l:
                parameter_map[v] = t
            args = [
                self.to_formula(c, parameter_map) for c in node.children[i:]
            ]
            for v, t in l:
                del (parameter_map[v])
            return Forall(l, args)

        i = 0
        args = [self.to_formula(c, parameter_map) for c in node.children[i:]]

        def handle_modality(node, pref_len, modality):

            assert 1 <= len(
                node.children) <= 2, "Error: Found %d children." % len(
                    node.children)

            #print "%s / %s / %s" % (str(node), str(pref_len), str(modality))

            ag = node.name[pref_len:-1]

            if len(node.children) == 1:
                pred = self.to_formula(node.children[0], parameter_map)
            else:
                pred = self.to_formula(node.children[1], parameter_map)
                pred.negated_rml = True

            assert not isinstance(
                pred, Not
            ), "Error: Cannot nest lack of belief with (not ...): %s" % pred.dump(
            )
            assert isinstance(
                pred, Primitive
            ), "Error: Type should have been Primitive, but was %s" % str(
                type(pred))

            pred.agent_list = "%s%s %s" % (modality, ag, pred.agent_list)

            return pred

        if "and" == node.name:
            return And(args)
        elif "or" == node.name:
            return Or(args)
        elif "oneof" == node.name:
            return Oneof(args)
        elif "not" == node.name:
            return Not(args)
        elif "xor" == node.name:
            return Xor(args)
        elif "nondet" == node.name:
            assert len(node.children) == 1,\
                                       "nondet must only have a single child as a predicate"
            # make p != p2, otherwise might run into issues with mutation in some later step
            return Oneof([args[0], Not(args)])
        elif "unknown" == node.name:
            assert len(node.children) == 1,\
                "unknown must only have a single child as a predicate"
            # make p != p2, otherwise might run into issues with mutation in some later step
            p = Primitive(
                self.to_predicate(node.children[0], map=parameter_map))
            p2 = Primitive(
                self.to_predicate(node.children[0], map=parameter_map))
            return Xor([p, Not([p2])])
        elif "when" == node.name:
            assert len(args) == 2,\
                "When clause must have exactly 2 children"
            return When(args[0], args[1])

        elif "P{" == node.name[:2]:
            return handle_modality(node, 2, 'P')

        elif "!P{" == node.name[:3]:
            return handle_modality(node, 3, '!P')

        elif "B{" == node.name[:2]:
            return handle_modality(node, 2, 'B')

        elif "!B{" == node.name[:3]:
            return handle_modality(node, 3, '!B')

        elif "!" == node.name[0]:
            node.name = node.name[1:]
            pred = Primitive(self.to_predicate(node, map=parameter_map))
            pred.negated_rml = True
            return pred
        else:
            # it's a predicate
            return Primitive(self.to_predicate(node, map=parameter_map))