def __init__(self, problem, state, serialize=True, ignore_mutexes=False):
        """
        Parameters
        ----------
        problem : PlanningProblem
            An instance of the PlanningProblem class

        state : tuple(bool)
            An ordered sequence of True/False values indicating the literal value
            of the corresponding fluent in problem.state_map

        serialize : bool
            Flag indicating whether to serialize non-persistence actions. Actions
            should NOT be serialized for regression search (e.g., GraphPlan), and
            _should_ be serialized if the planning graph is being used to estimate
            a heuristic
        """
        self._serialize = serialize
        self._is_leveled = False
        self._ignore_mutexes = ignore_mutexes
        self.goal = set(problem.goal)

        # make no-op actions that persist every literal to the next layer
        no_ops = [make_node(n, no_op=True) for n in chain(*(makeNoOp(s) for s in problem.state_map))]
        self._actionNodes = no_ops + [make_node(a) for a in problem.actions_list]
        
        # initialize the planning graph by finding the literals that are in the
        # first layer and finding the actions they they should be connected to
        literals = [s if f else ~s for f, s in zip(state, problem.state_map)]
        layer = LiteralLayer(literals, ActionLayer(), self._ignore_mutexes)
        layer.update_mutexes()
        self.literal_layers = [layer]
        self.action_layers = []
    def setUp(self):
        super().setUp()
        # eat has precondition Have(cake) and bake has precondition ~Have(cake)
        # which are logical inverses, so eat & bake should be mutex at every
        # level of the planning graph where both actions appear
        self.competing_needs_actions = [self.eat_action, self.bake_action]

        # competing needs tests -- build two copies of the planning graph: one where
        #  A, B, and C are pairwise mutex, and another where they are not
        A, B, C = expr('FakeFluent_A'), expr('FakeFluent_B'), expr(
            'FakeFluent_C')
        self.fake_competing_needs_actions = [
            make_node(
                Action(expr('FakeAction(A)'), [set([A]), set()],
                       [set([A]), set()])),
            make_node(
                Action(expr('FakeAction(B)'), [set([B]), set()],
                       [set([B]), set()])),
            make_node(
                Action(expr('FakeAction(C)'), [set([C]), set()],
                       [set([C]), set()]))
        ]
        competing_layer = LiteralLayer([A, B, C], ActionLayer())
        for a1, a2 in combinations([A, B, C], 2):
            competing_layer.set_mutex(a1, a2)
        self.competing_action_layer = ActionLayer(competing_layer.parent_layer,
                                                  competing_layer, False, True)
        for action in self.fake_competing_needs_actions:
            self.competing_action_layer.add(action)
            competing_layer |= action.effects
            competing_layer.add_outbound_edges(action, action.preconditions)
            self.competing_action_layer.add_inbound_edges(
                action, action.preconditions)
            self.competing_action_layer.add_outbound_edges(
                action, action.effects)

        not_competing_layer = LiteralLayer([A, B, C], ActionLayer())
        self.not_competing_action_layer = ActionLayer(
            not_competing_layer.parent_layer, not_competing_layer, False, True)
        for action in self.fake_competing_needs_actions:
            self.not_competing_action_layer.add(action)
            not_competing_layer |= action.effects
            not_competing_layer.add_outbound_edges(action,
                                                   action.preconditions)
            self.not_competing_action_layer.add_inbound_edges(
                action, action.preconditions)
            self.not_competing_action_layer.add_outbound_edges(
                action, action.effects)
Beispiel #3
0
    def setUp(self):
        super().setUp()
        # bake has the effect Have(Cake) which is the logical negation of the effect
        # ~Have(cake) from the persistence action ~NoOp::Have(cake)
        no_ops = [a for a in self.cake_pg._actionNodes if a.no_op]
        self.inconsistent_effects_actions = [self.bake_action, no_ops[3]]

        X, Y = expr('FakeFluent_X'), expr('FakeFluent_Y')
        self.fake_not_inconsistent_effects_actions = [
            make_node(
                Action(expr('FakeAction(X)'), [set([X]), set()],
                       [set([X]), set()])),
            make_node(
                Action(expr('FakeAction(Y)'), [set([Y]), set()],
                       [set([Y]), set()])),
        ]
    def setUp(self):
        super().setUp()
        # the persistence action ~NoOp::Have(cake) has the effect ~Have(cake), which is
        # the logical negation of Have(cake) -- the precondition for the Eat(cake) action
        no_ops = [a for a in self.cake_pg._actionNodes if a.no_op]
        self.interference_actions = [self.eat_action, no_ops[3]]

        X, Y = expr('FakeFluent_X'), expr('FakeFluent_Y')
        self.fake_interference_actions = [
            make_node(
                Action(expr('FakeAction(X)'), [set([X]), set()],
                       [set([X]), set()])),
            make_node(
                Action(expr('FakeAction(Y)'), [set([Y]), set()],
                       [set([Y]), set()])),
        ]
Beispiel #5
0
    def setUp(self):
        self.cake_problem = have_cake()
        self.cake_pg = PlanningGraph(self.cake_problem,
                                     self.cake_problem.initial,
                                     serialize=False).fill()

        self.eat_action, self.bake_action = [
            a for a in self.cake_pg._actionNodes if not a.no_op
        ]
        no_ops = [a for a in self.cake_pg._actionNodes if a.no_op]
        self.null_action = make_node(
            Action(expr('Null()'), [set(), set()], [set(), set()]))

        # some independent nodes for testing mutexes
        at_here = expr('At(here)')
        at_there = expr('At(there)')
        self.pos_literals = [at_here, at_there]
        self.neg_literals = [~x for x in self.pos_literals]
        self.literal_layer = LiteralLayer(
            self.pos_literals + self.neg_literals, ActionLayer())
        self.literal_layer.update_mutexes()

        # independent actions for testing mutex
        self.actions = [
            make_node(
                Action(expr('Go(here)'), [set(), set()],
                       [set([at_here]), set()])),
            make_node(
                Action(expr('Go(there)'), [set(), set()],
                       [set([at_there]), set()]))
        ]
        self.no_ops = [
            make_node(x)
            for x in chain(*(makeNoOp(l) for l in self.pos_literals))
        ]
        self.action_layer = ActionLayer(self.no_ops + self.actions,
                                        self.literal_layer)
        self.action_layer.update_mutexes()
        for action in self.no_ops + self.actions:
            self.action_layer.add_inbound_edges(action, action.preconditions)
            self.action_layer.add_outbound_edges(action, action.effects)
Beispiel #6
0
    def setUp(self):
        self.cake_problem = have_cake()
        self.cake_pg = PlanningGraph(self.cake_problem,
                                     self.cake_problem.initial,
                                     serialize=False).fill()

        eat_action, bake_action = [
            a for a in self.cake_pg._actionNodes if not a.no_op
        ]
        no_ops = [a for a in self.cake_pg._actionNodes if a.no_op]

        # bake has the effect Have(Cake) which is the logical negation of the effect
        # ~Have(cake) from the persistence action ~NoOp::Have(cake)
        self.inconsistent_effects_actions = [bake_action, no_ops[3]]

        # the persistence action ~NoOp::Have(cake) has the effect ~Have(cake), which is
        # the logical negation of Have(cake) -- the precondition for the Eat(cake) action
        self.interference_actions = [eat_action, no_ops[3]]

        # eat has precondition Have(cake) and bake has precondition ~Have(cake)
        # which are logical inverses, so eat & bake should be mutex at every
        # level of the planning graph where both actions appear
        self.competing_needs_actions = [eat_action, bake_action]

        self.ac_problem = air_cargo_p1()
        self.ac_pg_serial = PlanningGraph(self.ac_problem,
                                          self.ac_problem.initial).fill()
        # In(C1, P2) and In(C2, P1) have inconsistent support when they first appear in
        # the air cargo problem,
        self.inconsistent_support_literals = [
            expr("In(C1, P2)"), expr("In(C2, P1)")
        ]

        # some independent nodes for testing mutexes
        at_here = expr('At(here)')
        at_there = expr('At(there)')
        self.pos_literals = [at_here, at_there]
        self.neg_literals = [~x for x in self.pos_literals]
        self.literal_layer = LiteralLayer(
            self.pos_literals + self.neg_literals, ActionLayer())
        self.literal_layer.update_mutexes()

        # independent actions for testing mutex
        self.actions = [
            make_node(
                Action(expr('Go(here)'), [set(), set()],
                       [set([at_here]), set()])),
            make_node(
                Action(expr('Go(there)'), [set(), set()],
                       [set([at_there]), set()]))
        ]
        self.no_ops = [
            make_node(x)
            for x in chain(*(makeNoOp(l) for l in self.pos_literals))
        ]
        self.action_layer = ActionLayer(self.no_ops + self.actions,
                                        self.literal_layer)
        self.action_layer.update_mutexes()
        for action in self.no_ops + self.actions:
            self.action_layer.add_inbound_edges(action, action.preconditions)
            self.action_layer.add_outbound_edges(action, action.effects)

        # competing needs tests -- build two copies of the planning graph: one where
        #  A, B, and C are pairwise mutex, and another where they are not
        A, B, C = expr('A'), expr('B'), expr('C')
        self.fake_competing_needs_actions = [
            make_node(
                Action(expr('FakeAction(A)'), [set([A]), set()],
                       [set([A]), set()])),
            make_node(
                Action(expr('FakeAction(B)'), [set([B]), set()],
                       [set([B]), set()])),
            make_node(
                Action(expr('FakeAction(C)'), [set([C]), set()],
                       [set([C]), set()]))
        ]
        competing_layer = LiteralLayer([A, B, C], ActionLayer())
        for a1, a2 in combinations([A, B, C], 2):
            competing_layer.set_mutex(a1, a2)
        self.competing_action_layer = ActionLayer(competing_layer.parent_layer,
                                                  competing_layer, False, True)
        for action in self.fake_competing_needs_actions:
            self.competing_action_layer.add(action)
            competing_layer |= action.effects
            competing_layer.add_outbound_edges(action, action.preconditions)
            self.competing_action_layer.add_inbound_edges(
                action, action.preconditions)
            self.competing_action_layer.add_outbound_edges(
                action, action.effects)

        not_competing_layer = LiteralLayer([A, B, C], ActionLayer())
        self.not_competing_action_layer = ActionLayer(
            not_competing_layer.parent_layer, not_competing_layer, False, True)
        for action in self.fake_competing_needs_actions:
            self.not_competing_action_layer.add(action)
            not_competing_layer |= action.effects
            not_competing_layer.add_outbound_edges(action,
                                                   action.preconditions)
            self.not_competing_action_layer.add_inbound_edges(
                action, action.preconditions)
            self.not_competing_action_layer.add_outbound_edges(
                action, action.effects)