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()])