Exemplo n.º 1
0
class PlanGraphLevel(object):
    """
    A class for representing a level in the plan graph.
    For each level i, the PlanGraphLevel consists of the actionLayer and propositionLayer at this level in this order!
    """
    independent_actions = set()  # updated to the independent_actions of the problem (graph_plan.py line 32)
    actions = []  # updated to the actions of the problem (graph_plan.py line 33 and planning_problem.py line 36)
    props = []  # updated to the propositions of the problem (graph_plan.py line 34 and planning_problem.py line 36)

    @staticmethod
    def set_independent_actions(independent_actions):
        PlanGraphLevel.independent_actions = independent_actions

    @staticmethod
    def set_actions(actions):
        PlanGraphLevel.actions = actions

    @staticmethod
    def set_props(props):
        PlanGraphLevel.props = props

    def __init__(self):
        """
        Constructor
        """
        self.action_layer = ActionLayer()  # see action_layer.py
        self.proposition_layer = PropositionLayer()  # see proposition_layer.py

    def get_proposition_layer(self):  # returns the proposition layer
        return self.proposition_layer

    def set_proposition_layer(self, prop_layer):  # sets the proposition layer
        self.proposition_layer = prop_layer

    def get_action_layer(self):  # returns the action layer
        return self.action_layer

    def set_action_layer(self, action_layer):  # sets the action layer
        self.action_layer = action_layer

    def update_action_layer(self, previous_proposition_layer):
        """
        Updates the action layer given the previous proposition layer (see proposition_layer.py)
        You should add an action to the layer if its preconditions are in the previous propositions layer,
        and the preconditions are not pairwise mutex.
        all_actions is the set of all the action (include noOp) in the domain

        You might want to use those functions:
        previous_proposition_layer.is_mutex(prop1, prop2) returns true
        if prop1 and prop2 are mutex at the previous propositions layer
        previous_proposition_layer.all_preconds_in_layer(action) returns true
        if all the preconditions of action are in the previous propositions layer
        self.actionLayer.addAction(action) adds action to the current action layer
        """
        all_actions = PlanGraphLevel.actions
        for act in all_actions:
            if previous_proposition_layer.all_preconds_in_layer(act):
                preconds = act.get_pre()
                if not any([previous_proposition_layer.is_mutex(p1, p1) for p1, p2 in itertools.combinations(preconds, 2)]):
                    self.action_layer.add_action(act)

    def update_mutex_actions(self, previous_layer_mutex_proposition):
        """
        Updates the mutex set in self.action_layer,
        given the mutex proposition from the previous layer.
        current_layer_actions are the actions in the current action layer
        You might want to use this function:
        self.actionLayer.add_mutex_actions(action1, action2)
        adds the pair (action1, action2) to the mutex set in the current action layer
        Note that an action is *not* mutex with itself
        """
        current_layer_actions = self.action_layer.get_actions()
        for act1, act2 in itertools.combinations(current_layer_actions, 2):
            if act1 is not act2 and mutex_actions(act1, act2, previous_layer_mutex_proposition):
                self.action_layer.add_mutex_actions(act1, act2)

    def update_proposition_layer(self):
        """
        Updates the propositions in the current proposition layer,
        given the current action layer.
        don't forget to update the producers list!
        Note that same proposition in different layers might have different producers lists,
        hence you should create two different instances.
        current_layer_actions is the set of all the actions in the current layer.
        You might want to use those functions:
        dict() creates a new dictionary that might help to keep track on the propositions that you've
               already added to the layer
        self.proposition_layer.add_proposition(prop) adds the proposition prop to the current layer

        """
        current_layer_actions = self.action_layer.get_actions()
        props = {}
        for act in current_layer_actions:
            for p in (set(act.get_pre()) - set(act.get_delete())) | set(act.get_add()):
                if p not in props.keys():
                    props[p] = Proposition(p.get_name())
                props[p].add_producer(act)

        for prop in props.values():
            self.proposition_layer.add_proposition(prop)

    def update_mutex_proposition(self):
        """
        updates the mutex propositions in the current proposition layer
        You might want to use those functions:
        mutex_propositions(prop1, prop2, current_layer_mutex_actions) returns true
        if prop1 and prop2 are mutex in the current layer
        self.proposition_layer.add_mutex_prop(prop1, prop2) adds the pair (prop1, prop2)
        to the mutex set of the current layer
        """
        current_layer_mutex_actions = self.action_layer.get_mutex_actions()
        for p1, p2 in itertools.combinations(self.proposition_layer.get_propositions(), 2):
            if p1 != p2 and mutex_propositions(p1, p2, current_layer_mutex_actions):
                self.proposition_layer.add_mutex_prop(p1, p2)

    def expand(self, previous_layer):
        """
        Your algorithm should work as follows:
        First, given the propositions and the list of mutex propositions from the previous layer,
        set the actions in the action layer.
        Then, set the mutex action in the action layer.
        Finally, given all the actions in the current layer,
        set the propositions and their mutex relations in the proposition layer.
        """
        previous_proposition_layer = previous_layer.get_proposition_layer()
        previous_layer_mutex_proposition = previous_proposition_layer.get_mutex_props()

        # set actions at action layer
        self.update_action_layer(previous_proposition_layer)

        # set mutex action in the action layer
        self.update_mutex_actions(previous_layer_mutex_proposition)

        # with actions of current layer: set propositions and their mutex relations in proposition layer
        self.update_proposition_layer()
        self.update_mutex_proposition()

    def expand_without_mutex(self, previous_layer):
        """
        Questions 11 and 12
        You don't have to use this function
        """
        previous_proposition_layer = previous_layer.get_proposition_layer()
        self.update_action_layer(previous_proposition_layer)
        self.update_proposition_layer()
Exemplo n.º 2
0
 def __init__(self):
     """
     Constructor
     """
     self.action_layer = ActionLayer()  # see action_layer.py
     self.proposition_layer = PropositionLayer()  # see proposition_layer.py
Exemplo n.º 3
0
class PlanGraphLevel(object):
    """
    A class for representing a level in the plan graph.
    For each level i, the PlanGraphLevel consists of the actionLayer and propositionLayer at this level in this order!
    """
    independent_actions = set(
    )  # updated to the independent_actions of the problem (graph_plan.py line 32)
    actions = [
    ]  # updated to the actions of the problem (graph_plan.py line 33 and planning_problem.py line 36)
    props = [
    ]  # updated to the propositions of the problem (graph_plan.py line 34 and planning_problem.py line 36)

    @staticmethod
    def set_independent_actions(independent_actions):
        PlanGraphLevel.independent_actions = independent_actions

    @staticmethod
    def set_actions(actions):
        PlanGraphLevel.actions = actions

    @staticmethod
    def set_props(props):
        PlanGraphLevel.props = props

    def __init__(self):
        """
        Constructor
        """
        self.action_layer = ActionLayer()  # see action_layer.py
        self.proposition_layer = PropositionLayer()  # see proposition_layer.py

    def get_proposition_layer(self):  # returns the proposition layer
        return self.proposition_layer

    def set_proposition_layer(self, prop_layer):  # sets the proposition layer
        self.proposition_layer = prop_layer

    def get_action_layer(self):  # returns the action layer
        return self.action_layer

    def set_action_layer(self, action_layer):  # sets the action layer
        self.action_layer = action_layer

    def update_action_layer(self, previous_proposition_layer):
        """
        Updates the action layer given the previous proposition layer (see proposition_layer.py)
        You should add an action to the layer if its preconditions are in the previous propositions layer,
        and the preconditions are not pairwise mutex.
        all_actions is the set of all the action (include noOp) in the domain
        You might want to use those functions:
        previous_proposition_layer.is_mutex(prop1, prop2) returns true
        if prop1 and prop2 are mutex at the previous propositions layer
        previous_proposition_layer.all_preconds_in_layer(action) returns true
        if all the preconditions of action are in the previous propositions layer
        self.actionLayer.addAction(action) adds action to the current action layer
        """
        all_actions = PlanGraphLevel.actions
        for a in all_actions:
            if previous_proposition_layer.all_preconds_in_layer(a):
                if not self.action_pre_req_mutexed(a,
                                                   previous_proposition_layer):
                    self.action_layer.add_action(a)

    @staticmethod
    def action_pre_req_mutexed(action, previous_proposition_layer):
        for p1 in action.get_pre():
            for p2 in action.get_pre():
                if p1 != p2 and previous_proposition_layer.is_mutex(p1, p2):
                    return True
        return False

    def update_mutex_actions(self, previous_layer_mutex_proposition):
        """
        Updates the mutex set in self.action_layer,
        given the mutex proposition from the previous layer.
        current_layer_actions are the actions in the current action layer
        You might want to use this function:
        self.actionLayer.add_mutex_actions(action1, action2)
        adds the pair (action1, action2) to the mutex set in the current action layer
        Note that an action is *not* mutex with itself
        """
        current_layer_actions = self.action_layer.get_actions()
        for a1 in current_layer_actions:
            for a2 in current_layer_actions:
                if a1 != a2 and mutex_actions(
                        a1, a2, previous_layer_mutex_proposition):
                    self.action_layer.add_mutex_actions(a1, a2)

    def update_proposition_layer(self):
        """
        Updates the propositions in the current proposition layer,
        given the current action layer.
        don't forget to update the producers list!
        Note that same proposition in different layers might have different producers lists,
        hence you should create two different instances.
        current_layer_actions is the set of all the actions in the current layer.
        You might want to use those functions:
        dict() creates a new dictionary that might help to keep track on the propositions that you've
               already added to the layer
        self.proposition_layer.add_proposition(prop) adds the proposition prop to the current layer

        """
        current_layer_actions = self.action_layer.get_actions()
        props_and_producers = {}
        for a in current_layer_actions:
            added_propositions = a.get_add()
            for added in added_propositions:
                if added not in props_and_producers:
                    props_and_producers[added] = [a]
                else:
                    props_and_producers[added].append(a)
        for key, value in props_and_producers.items():
            new_prop = Proposition(key.name)
            new_prop.set_producers(value)
            self.proposition_layer.add_proposition(new_prop)

    def update_mutex_proposition(self):
        """
        updates the mutex propositions in the current proposition layer
        You might want to use those functions:
        mutex_propositions(prop1, prop2, current_layer_mutex_actions) returns true
        if prop1 and prop2 are mutex in the current layer
        self.proposition_layer.add_mutex_prop(prop1, prop2) adds the pair (prop1, prop2)
        to the mutex set of the current layer
        """
        current_layer_propositions = self.proposition_layer.get_propositions()
        current_layer_mutex_actions = self.action_layer.get_mutex_actions()
        for p1 in current_layer_propositions:
            for p2 in current_layer_propositions:
                if p1 != p2 and mutex_propositions(
                        p1, p2, current_layer_mutex_actions):
                    self.proposition_layer.add_mutex_prop(p1, p2)

    def expand(self, previous_layer):
        """
        Your algorithm should work as follows:
        First, given the propositions and the list of mutex propositions from the previous layer,
        set the actions in the action layer.
        Then, set the mutex action in the action layer.
        Finally, given all the actions in the current layer,
        set the propositions and their mutex relations in the proposition layer.
        """
        previous_proposition_layer = previous_layer.get_proposition_layer()
        previous_layer_mutex_proposition = previous_proposition_layer.get_mutex_props(
        )
        self.update_action_layer(previous_proposition_layer)
        self.update_mutex_actions(previous_layer_mutex_proposition)
        self.update_proposition_layer()
        self.update_mutex_proposition()

    def expand_without_mutex(self, previous_layer):
        """
        Questions 11 and 12
        You don't have to use this function
        """
        previous_proposition_layer = previous_layer.get_proposition_layer()
        self.update_action_layer(previous_proposition_layer)
        self.update_proposition_layer()
Exemplo n.º 4
0
    def graph_plan(self):
        """
        The graphplan algorithm.
        The code calls the extract function which you should complete below
        """
        # initialization
        init_state = self.initial_state
        level = 0
        self.no_goods = [
        ]  # make sure you update noGoods in your backward search!
        self.no_goods.append([])
        # create first layer of the graph, note it only has a proposition layer which consists of the initial state.
        prop_layer_init = PropositionLayer()
        for prop in init_state:
            prop_layer_init.add_proposition(prop)
        pg_init = PlanGraphLevel()
        pg_init.set_proposition_layer(prop_layer_init)
        self.graph.append(pg_init)
        size_no_good = -1
        """
        While the layer does not contain all of the propositions in the goal state,
        or some of these propositions are mutex in the layer we,
        and we have not reached the fixed point, continue expanding the graph
        """

        while self.goal_state_not_in_prop_layer(self.graph[level].get_proposition_layer().get_propositions()) or \
                self.goal_state_has_mutex(self.graph[level].get_proposition_layer()):
            if self.is_fixed(level):
                return None
                # this means we stopped the while loop above because we reached a fixed point in the graph.
                #  nothing more to do, we failed!

            self.no_goods.append([])
            level = level + 1
            pg_next = PlanGraphLevel()  # create new PlanGraph object
            pg_next.expand(
                self.graph[level - 1]
            )  # calls the expand function, which you are implementing in the PlanGraph class
            self.graph.append(
                pg_next)  # appending the new level to the plan graph

            size_no_good = len(
                self.no_goods[level])  # remember size of nogood table
        if self.goal_state_has_mutex(
                self.graph[level].get_proposition_layer()):
            print("gal state mutex")
        plan_solution = self.extract(self.graph, self.goal, level)
        # try to extract a plan since all of the goal propositions are in current graph level, and are not mutex

        while plan_solution is None:  # while we didn't extract a plan successfully
            level = level + 1
            self.no_goods.append([])
            pg_next = PlanGraphLevel(
            )  # create next level of the graph by expanding
            pg_next.expand(
                self.graph[level -
                           1])  # create next level of the graph by expanding
            self.graph.append(pg_next)
            plan_solution = self.extract(self.graph, self.goal,
                                         level)  # try to extract a plan again
            if plan_solution is None and self.is_fixed(
                    level):  # if failed and reached fixed point
                # if len(self.no_goods[level - 1]) == len(self.no_goods[level]):   MISTAKE????????????????????
                if size_no_good == len(self.no_goods[level]):
                    # if size of nogood didn't change, means there's nothing more to do. We failed.
                    return None
                size_no_good = len(
                    self.no_goods[level]
                )  # we didn't fail yet! update size of no good
        return plan_solution
Exemplo n.º 5
0
class PlanGraphLevel(object):
    """
    A class for representing a level in the plan graph.
    For each level i, the PlanGraphLevel consists of the actionLayer and propositionLayer at this level in this order!
    """
    independent_actions = set(
    )  # updated to the independent_actions of the problem (graph_plan.py line 32)
    actions = [
    ]  # updated to the actions of the problem (graph_plan.py line 33 and planning_problem.py line 36)
    props = [
    ]  # updated to the propositions of the problem (graph_plan.py line 34 and planning_problem.py line 36)

    @staticmethod
    def set_independent_actions(independent_actions):
        PlanGraphLevel.independent_actions = independent_actions

    @staticmethod
    def set_actions(actions):
        PlanGraphLevel.actions = actions

    @staticmethod
    def set_props(props):
        PlanGraphLevel.props = props

    def __init__(self):
        """
        Constructor
        """
        self.action_layer = ActionLayer()  # see action_layer.py
        self.proposition_layer = PropositionLayer()  # see proposition_layer.py

    def get_proposition_layer(self):  # returns the proposition layer
        return self.proposition_layer

    def set_proposition_layer(self, prop_layer):  # sets the proposition layer
        self.proposition_layer = prop_layer

    def get_action_layer(self):  # returns the action layer
        return self.action_layer

    def set_action_layer(self, action_layer):  # sets the action layer
        self.action_layer = action_layer

    def update_action_layer(self, previous_proposition_layer):
        """
        Updates the action layer given the previous proposition layer (see proposition_layer.py)
        You should add an action to the layer if its preconditions are in the previous propositions layer,
        and the preconditions are not pairwise mutex.
        all_actions is the set of all the action (include noOp) in the domain
        You might want to use those functions:
        previous_proposition_layer.is_mutex(prop1, prop2) returns true
        if prop1 and prop2 are mutex at the previous propositions layer
        previous_proposition_layer.all_preconds_in_layer(action) returns true
        if all the preconditions of action are in the previous propositions layer
        self.actionLayer.addAction(action) adds action to the current action layer
        """
        all_actions = PlanGraphLevel.actions

        def admissible_act(action):
            if not previous_proposition_layer.all_preconds_in_layer(action):
                return False

            props = action.get_pre()

            for i in range(0, len(props)):
                for j in range(i + 1, len(props)):

                    prop_1 = props[i]
                    prop_2 = props[j]

                    if previous_proposition_layer.is_mutex(prop_1, prop_2):
                        return False

            return True

        for act in all_actions:
            if admissible_act(act):
                self.action_layer.add_action(act)

    def update_mutex_actions(self, previous_layer_mutex_proposition):
        """
        Updates the mutex set in self.action_layer,
        given the mutex proposition from the previous layer.
        current_layer_actions are the actions in the current action layer
        You might want to use this function:
        self.actionLayer.add_mutex_actions(action1, action2)
        adds the pair (action1, action2) to the mutex set in the current action layer
        Note that an action is *not* mutex with itself
        """
        current_layer_actions = list(self.action_layer.get_actions())

        for i in range(0, len(current_layer_actions)):
            for j in range(i + 1, len(current_layer_actions)):

                if mutex_actions(current_layer_actions[i],
                                 current_layer_actions[j],
                                 previous_layer_mutex_proposition):
                    self.action_layer.add_mutex_actions(
                        current_layer_actions[i], current_layer_actions[j])

    def update_proposition_layer(self):
        """
        Updates the propositions in the current proposition layer,
        given the current action layer.
        don't forget to update the producers list!
        Note that same proposition in different layers might have different producers lists,
        hence you should create two different instances.
        current_layer_actions is the set of all the actions in the current layer.
        You might want to use those functions:
        dict() creates a new dictionary that might help to keep track on the propositions that you've
               already added to the layer
        self.proposition_layer.add_proposition(prop) adds the proposition prop to the current layer

        """
        current_layer_actions = self.action_layer.get_actions()

        updated_props = {}

        # checks for every action and adds to the dictionary of updated props the acts that led to is
        for act in current_layer_actions:
            for prop in act.get_add():
                if prop not in updated_props:
                    updated_props[prop] = list()
                updated_props[prop].append(act)

        # create new Proposition and add it to the new layer
        for proposition in updated_props:

            # create new prop
            new_prop = Proposition(proposition.get_name())
            # add its producers
            new_prop.set_producers(updated_props[proposition][:])
            # add to new layer
            self.proposition_layer.add_proposition(new_prop)

    def update_mutex_proposition(self):
        """
        updates the mutex propositions in the current proposition layer
        You might want to use those functions:
        mutex_propositions(prop1, prop2, current_layer_mutex_actions) returns true
        if prop1 and prop2 are mutex in the current layer
        self.proposition_layer.add_mutex_prop(prop1, prop2) adds the pair (prop1, prop2)
        to the mutex set of the current layer
        """
        current_layer_propositions = list(
            self.proposition_layer.get_propositions())
        current_layer_mutex_actions = list(
            self.action_layer.get_mutex_actions())

        for i in range(0, len(current_layer_propositions)):
            for j in range(i + 1, len(current_layer_propositions)):
                if mutex_propositions(current_layer_propositions[i],
                                      current_layer_propositions[j],
                                      current_layer_mutex_actions):
                    self.proposition_layer.add_mutex_prop(
                        current_layer_propositions[i],
                        current_layer_propositions[j])

    def expand(self, previous_layer):
        """
        Your algorithm should work as follows:
        First, given the propositions and the list of mutex propositions from the previous layer,
        set the actions in the action layer.
        Then, set the mutex action in the action layer.
        Finally, given all the actions in the current layer,
        set the propositions and their mutex relations in the proposition layer.
        """
        previous_proposition_layer = previous_layer.get_proposition_layer()
        previous_layer_mutex_proposition = previous_proposition_layer.get_mutex_props(
        )
        # update the action layer with previous prop layer
        self.update_action_layer(previous_proposition_layer)
        # update the mutex action in cur layer
        self.update_mutex_actions(previous_layer_mutex_proposition)

        #update the proposition layer
        self.update_proposition_layer()

        #finally update mutex
        self.update_mutex_proposition()

    def expand_without_mutex(self, previous_layer):
        """
        Questions 11 and 12
        You don't have to use this function
        """
        previous_layer_proposition = previous_layer

        self.update_action_layer(previous_layer_proposition)
        self.update_proposition_layer()