Exemple #1
0
class Environment(object):
    def __init__(self, dimension, agents, obstacles, agents_time):
        self.dimension = dimension
        self.obstacles = obstacles
        self.agents_time = agents_time

        self.agents = agents
        self.agent_dict = {}

        self.make_agent_dict()

        self.constraints = Constraints()
        self.constraint = {}

        self.a_star = AStar(self)

    def find_neighbors(self, state):
        neighbors = []

        # Wait action
        n = State(state.time + 1, state.location)
        if self.valid_state(n):
            neighbors.append(n)
        # Up action
        n = State(state.time + 1,
                  Location(state.location.x, state.location.y + 1))
        if self.valid_state(n) and self.valid_transition(state, n):
            neighbors.append(n)
        # Down action
        n = State(state.time + 1,
                  Location(state.location.x, state.location.y - 1))
        if self.valid_state(n) and self.valid_transition(state, n):
            neighbors.append(n)
        # Left action
        n = State(state.time + 1,
                  Location(state.location.x - 1, state.location.y))
        if self.valid_state(n) and self.valid_transition(state, n):
            neighbors.append(n)
        # Right action
        n = State(state.time + 1,
                  Location(state.location.x + 1, state.location.y))
        if self.valid_state(n) and self.valid_transition(state, n):
            neighbors.append(n)
        return neighbors

    def first_conflict(self, solution):
        maximum_t = max([len(plan) for plan in solution.values()])
        res = Conflict()
        for t in range(maximum_t):
            for agent_1, agent_2 in combinations(solution.keys(), 2):
                state_1 = self.find_state(agent_1, solution, t)
                state_2 = self.find_state(agent_2, solution, t)
                if state_1.is_equal_except_time(state_2):
                    res.time = t
                    res.type = Conflict.VERTEX
                    res.location_1 = state_1.location
                    res.agent_1 = agent_1
                    res.agent_2 = agent_2
                    return res

            for agent_1, agent_2 in combinations(solution.keys(), 2):
                state_1a = self.find_state(agent_1, solution, t)
                state_1b = self.find_state(agent_1, solution, t + 1)

                state_2a = self.find_state(agent_2, solution, t)
                state_2b = self.find_state(agent_2, solution, t + 1)

                if state_1a.is_equal_except_time(
                        state_2b) and state_1b.is_equal_except_time(state_2a):
                    res.time = t
                    res.type = Conflict.EDGE
                    res.agent_1 = agent_1
                    res.agent_2 = agent_2
                    res.location_1 = state_1a.location
                    res.location_2 = state_1b.location
                    return res
        return False

    def create_constraints(self, conflict):
        constraint = {}
        if conflict.type == Conflict.VERTEX:
            v_constraint = VertexConstraint(conflict.time, conflict.location_1)
            constraint = Constraints()
            constraint.vertex_constraints |= {v_constraint}
            constraint[conflict.agent_1] = constraint
            constraint[conflict.agent_2] = constraint

        elif conflict.type == Conflict.EDGE:
            constraint1 = Constraints()
            constraint2 = Constraints()

            e_constraint1 = EdgeConstraint(conflict.time, conflict.location_1,
                                           conflict.location_2)
            e_constraint2 = EdgeConstraint(conflict.time, conflict.location_2,
                                           conflict.location_1)

            constraint1.edge_constraints |= {e_constraint1}
            constraint2.edge_constraints |= {e_constraint2}

            constraint[conflict.agent_1] = constraint1
            constraint[conflict.agent_2] = constraint2

        return constraint

    def find_state(self, name, solution, t):
        if t < len(solution[name]):
            return solution[name][t]
        else:
            return solution[name][-1]

    def valid_state(self, state):
        return state.location.x >= 0 and state.location.x < self.dimension[0] \
            and state.location.y >= 0 and state.location.y < self.dimension[1] \
            and VertexConstraint(state.time, state.location) not in self.constraints.vertex_constraints \
            and (state.location.x, state.location.y) not in self.obstacles

    def valid_transition(self, state_1, state_2):
        return EdgeConstraint(
            state_1.time, state_1.location,
            state_2.location) not in self.constraints.edge_constraints

    def is_solution(self, name):
        pass

    def admissible_heuristic(self, state, name):
        goal = self.agent_dict[name]["goal"]
        return fabs(state.location.x -
                    goal.location.x) + fabs(state.location.y - goal.location.y)

    def is_at_goal(self, state, name):
        goal_state = self.agent_dict[name]["goal"]
        return state.is_equal_except_time(goal_state)

    def make_agent_dict(self):
        for agent in self.agents:

            start_state = State(self.agents_time[agent['name']],
                                Location(agent['start'][0], agent['start'][1]))
            goal_state = State(self.agents_time[agent['name']],
                               Location(agent['goal'][0], agent['goal'][1]))

            self.agent_dict.update(
                {agent['name']: {
                     'start': start_state,
                     'goal': goal_state
                 }})

    def compute_solution(self):
        solution = {}
        for agent in self.agent_dict.keys():
            self.constraints = self.constraint.setdefault(agent, Constraints())
            local_solution = self.a_star.find(agent)
            if not local_solution:
                return False
            solution.update({agent: local_solution})
        return solution

    def compute_solution_cost(self, solution):
        return sum([len(path) for path in solution.values()])