def process(self): '''Process buy orders in an optimal match-up fashion. O(n2) time.''' # A buy order for $x can only be processed if there is an existing sell order with price $y # such that $x >= $y. summary = '' temp_buyers = PriorityQueue() # Create a temp pq for buyers while self.buyers.peek() is not None: # Iterate all buyers buyer = self.buyers.pop() # Get the next buyer temp_sellers = PriorityQueue() buyer_matched = False # Assume there's no match for this buyer while self.sellers.peek() is not None: seller = self.sellers.pop() # Get the next seller if buyer._key >= seller._key: # This is a valid matchup buyer_matched = True summary += ('Buyer $' + str(buyer._key) + ' matched with seller $' + str(seller._key) + '\n') else: # if this seller was no good, push it on the temp seller pq temp_sellers.push(seller._key, seller._value) self.sellers = temp_sellers # Copy the temp seller pq back to the original if not buyer_matched: temp_buyers.push(buyer._key, buyer._value) self.buyers = temp_buyers # Copy the temp buyer pq back to the original return summary
def test_priority_queue(make_jobs): pq = PriorityQueue() assert pq.jobs == [] assert pq._iterations == 0 pq = PriorityQueue(make_jobs) temp = [p.priority for p in pq.jobs] assert temp == [9, 9, 9, 7, 8, 3, 7, 3, 7, 4]
def __init__(self, board, data): self.board = board self.data = data self.forward_begin_state = State(self.board, None, None, 0, 0, 0) self.forward_data = Data(data.board_num, data.heuristic, data.time_limit, data.indicators, data.given_solution, data.min_cost_path, data.use_difficulty) self.forward_data.bidirectional_direction = BidirectionalDirection.FORWARD self.forward_f_values = dict() self.forward_open_list = PriorityQueue() self.forward_closed_list = set() state = self.forward_begin_state.run_steps_on_board(data, False, False) self.backward_begin_state = State(state.board, None, None, 0, 0, 0) self.backward_data = Data(data.board_num, data.heuristic, data.time_limit, data.indicators, data.given_solution, data.min_cost_path, data.use_difficulty) self.backward_data.bidirectional_direction = BidirectionalDirection.BACKWARD self.backward_f_values = dict() self.backward_open_list = PriorityQueue() self.backward_closed_list = set() self.forward_data.goal_board = self.backward_begin_state.board self.backward_data.goal_board = self.forward_begin_state.board f = self.forward_begin_state.calculate_f(self.forward_data) self.forward_begin_state.f_value = f self.forward_f_values[hash(self.forward_begin_state.board.grid_to_str())] = f self.forward_open_list.push(self.forward_begin_state) f = self.backward_begin_state.calculate_f(self.backward_data) self.backward_begin_state.f_value = f self.backward_f_values[hash(self.backward_begin_state.board.grid_to_str())] = f self.backward_open_list.push(self.backward_begin_state) self.forward_prev_state = None self.backward_prev_sate = None
def shortest_path(self, source, destination=None, q=None): ''' API: shortest_path(self, source, destination = None, display = None) Description: Generic implementation of Dijkstra's Algorithm. if destination is not specified: This method determines all nodes reachable from "source" ie. creates precedence tree and returns it (dictionary). if destination is given: If there exists a path from "source" to "destination" it will return list of the nodes is a shortest path. If there is no such path, it will return the precedence tree constructed from source (dictionary). Input: source: Search starts from node with this name. destination: Destination node name. Return: Returns predecessor tree in dictionary form if destination is not specified, returns list of node names in the path from source to destination if destination is specified and there is a path. If there is no path returns predecessor tree in dictionary form. See description section. Unit Test: >>> G = Network(type = UNDIRECTED_NETWORK, splines = 'true', K = 1.5, display = 'off') >>> G.random(numnodes = 7, density = 0.7, Euclidean = True, seedInput = 9) >>> print G.shortest_path(0) {1: 4, 2: 0, 3: 0, 4: 0, 5: 0, 6: 0} ''' # example how to modify some attribute for node # neighbors = self.neighbors # for i in self.get_node_list(): # self.get_node(i).set_attr('label', '-') # self.get_node(i).set_attr('distance', 0) q = PriorityQueue() s = PriorityQueue() for j in self.get_node_list(): q.push(j, float('inf')) q.push(source, 0) while not q.isEmpty(): current = q.peek() value = q.get_priority(current) q.remove(current) s.push(current, value) for i in self.get_neighbors(current): if i in q.aList: temp = value + self.get_edge_attr(current, i, 'cost') # if temp<q.get_priority(i): # q.push(i,temp) q.push(i, min(temp, q.get_priority(i))) if i is destination: break return q.aList, s.aList
def init(self): self._edge_labels_forward = [] self._edge_labels_backward = [] self._adjacency_list_forward = PriorityQueue() self._adjacency_list_backward = PriorityQueue() self._edges_status_forward.clear() self._edges_status_backward.clear() self._best_path = BestConnection(EdgeId(-1, -1), EdgeId(-1, -1), float('inf')) self._threshold: float = float('inf')
def iterative_deepening_a_star_search(start_grid, use_manhattan): """ This function performs Iterative Deepening A* (IDA*) :param start_grid: initial configuration grid :param use_manhattan: tells whether to use manhattan heuristic or not :return: None """ """ Initialize the bound to the current f value of the root node instead of infinity like with branch_and_bound The algorithm calls for calling branch and bound, but a tweak was required, so the code is partially repeated """ root = Node(curr_grid=start_grid, goal_grid=goal_grid, use_manhattan=use_manhattan, move_str='') limit = root.f result_node = None num_nodes_expanded = 0 start_time = time.perf_counter() exec_time_str = '' """ Branch and Bound. See above method for details """ while result_node is None: evaluated_weight = INFINITY open_list = PriorityQueue() open_list.insert(root) while open_list.size() > 0: num_nodes_expanded += 1 current_node = open_list.delete() if current_node.h == 0 and current_node.f <= limit: end_time = time.perf_counter() exec_time = end_time - start_time exec_time_str = f'Execution Time: {exec_time:0.4f} seconds' limit = current_node.f result_node = current_node else: successors = current_node.generate_successors() temp_list = PriorityQueue() for successor in successors: if successor.f <= limit: temp_list.insert(successor) elif evaluated_weight > successor.f: evaluated_weight = successor.f while temp_list.size() > 0: open_list.insert(temp_list.delete()) limit = evaluated_weight # Update the weight trace_and_print(root, result_node, num_nodes_expanded, exec_time_str) # Call trace and print for the solution
def test_enqueue_dequeue_two(self): """ Dequeuing from a two-element queue returns the one with highest priority. """ pq = PriorityQueue() lower_priority = Job(1, 'of') higher_priority = Job(3, 'the') pq.enqueue(higher_priority) pq.enqueue(lower_priority) self.assertEqual(higher_priority, pq.dequeue()) pq = PriorityQueue() pq.enqueue(lower_priority) pq.enqueue(higher_priority) self.assertEqual(higher_priority, pq.dequeue())
def Dijkstra_algorithm(graph: Graph, starting_node: int) -> DijkstraAlgorithmResult: dist = [INFINITY for _ in range(graph.nodes_count)] prev = [None for _ in range(graph.nodes_count)] dist[starting_node] = 0 prev[starting_node] = starting_node # prepare list of tuples of nodes labels with their starting distances dist_nodes = [ PQNode(key=i, priority=dist[i]) for i in range(0, graph.nodes_count) ] Q = PriorityQueue(raw=dist_nodes) while not Q.is_empty: # pick the closest node fst = Q.pop().key for e in graph.get_neighbourhood(fst): # scan the neighbourhood snd = e.snd weight = e.weight if dist[snd] > dist[fst] + weight: # update if better route found dist[snd] = dist[fst] + weight prev[snd] = fst Q.bottom_bound_flatten_priority(snd, dist[snd]) return DijkstraAlgorithmResult(dist=dist, prev=prev)
def a_star(start, goal='Bucharest'): """ Retorna uma lista com o caminho de start até goal segundo o algoritmo A* """ # Cria uma fila prioritária onde os primeiros elementos sempre serão as possibilidades de rota mais curtas. queue = PriorityQueue(priority_asc=False) # Instancia o ponto de partida utilizando a estrutura City. start_city = City(start) # Adiciona o ponto de partida à fila prioritária. # Como o grau de prioridade não foi informado, será considerado O. queue.push(start_city.get_estimated_total_cost(), start_city) # Obtém-se a cidade com maior prioridade de ser expandida, que nesse momento ainda é o ponto inicial. city = queue.pop() # Enquanto a cidade prioritária não for o destino, continuaremos no laço. while city.is_name(goal) is False: # Expande as próximas cidades a partir da cidade atual. for next_city in dists.dists[city.name]: # Cria um novo ponto a partir do nome da próxima cidade, do custo de locomoção e da rota feita até aqui. new_city = City(name=next_city[0], cost=next_city[1], route_made=city.route_made) # Adiciona o ponto à fila prioritária dando o custo estimado até o destino como grau de prioridade. queue.push(new_city.get_estimated_total_cost(), new_city) # Atualiza a cidade a ser analisada pela próxima iteração. city = queue.pop() # Retorna uma lista contendo a melhor rota return [p.name for p in city.route_made]
def dijkstra(g, start): # Distance is the priority in PQ pq = PriorityQueue() visited = set() # Redundant as weighs are always positive distance = {} # Store distance to nodes from start previous = {} # Store the previous node to reach a node # Set all the weight to infinity for node_id in g.get_vertices(): distance[node_id] = float('inf') # infinity distance[start] = 0 # start to start have zero distance previous[start] = None # No previous for start # Add start to priority queue pq.add_with_priority(start, 0) while pq.length > 0: # PQ will have unvisited nodes node_id = pq.extract_min() node = g.vert_list[node_id] for neigh in node.get_neighs(): if neigh not in visited: n_dist = node.get_weight(neigh) # if distance to neigh is less through, node_id, update. if distance[node_id] + n_dist < distance[neigh]: distance[neigh] = distance[node_id] + n_dist previous[neigh] = node_id # Update/add neigh in PQ, with new distance pq.decrease_priority(neigh, distance[neigh]) # Done processing the node. Mark it as visited visited.add(node_id) print(distance) print(previous)
def trace_back(goal_node, start_node, v_distances, visited_nodes, n, mazearray, diags=False): # begin the list of nodes which will represent the path back, starting with the end node path = [goal_node] current_node = goal_node # Set the loop in motion until we get back to the start while current_node != start_node: # Start an empty priority queue for the current node to check all neighbours neighbour_distances = PriorityQueue() neighbours = get_neighbours(current_node, n, diags) # Had some errors during testing, not sure if this is still necessary try: distance = v_distances[current_node] except Exception as e: print(e) # For each neighbour of the current node, add its location and distance # to a priority queue for neighbour, ntype in neighbours: if neighbour in v_distances: distance = v_distances[neighbour] neighbour_distances.push(distance, neighbour) # Pop the lowest value off; that is the next node in our path distance, smallest_neighbour = neighbour_distances.pop() mazearray[smallest_neighbour[0]][smallest_neighbour[1]].update(is_path=True) path.append(smallest_neighbour) current_node = smallest_neighbour mazearray[start_node[0]][start_node[1]].update(is_path=True)
def dijkstra(g, n, origin=0): # Set initial condition for dijkstra algorithm toVisit = [True] * n dist = [sys.maxint] * n pq = PriorityQueue() for u in range(n): if u == origin: pq.push([0, u]) else: pq.push([sys.maxint, u]) while not pq.empty(): cost, u = pq.pop() toVisit[u] = False for v in range(0, n): if g[u][v] != 0 and toVisit[v] and cost + g[u][v] < pq[v]: pq.push([g[u][v] + cost, v]) dist[v] = pq[v] print("(origem, destino) -> custo") for i in range(1, n): print("({}, {}) -> {}".format(origin, i, dist[i]))
def dijkstra(g, start): # Distance is the priority in PQ pq = PriorityQueue() visited = set() # Redundant as weighs are always positive distance = {} # Store distance to nodes from start previous = {} # Store the previous node to reach a node # prepare the start node distance[start] = 0 # start to start have zero distance previous[start] = None # No previous for start # Add start to priority queue pq.add_with_priority(start, 0) while pq.length > 0: # PQ will have unvisited nodes node_id = pq.extract_min() node = g.vert_list[node_id] for neigh in node.get_neighs(): if neigh not in visited: n_dist = node.get_weight(neigh) # if distance to neigh is less through, node_id, update. if neigh not in distance or distance[node_id] + n_dist < distance[neigh]: distance[neigh] = distance[node_id] + n_dist previous[neigh] = node_id # Update/add neigh in PQ, with new distance # Here, decrease_priority will add as well as update. # If such is not available, we will have to prepare PQ with # all nodes with float('inf') distance, except start pq.decrease_priority(neigh, distance[neigh]) # Done processing the node. Mark it as visited visited.add(node_id) print(distance) print(previous)
def mst(wg: WeightedGraph[V], start: int = 0) -> Optional[WeightedPath]: if start > (wg.vertex_count - 1) or start < 0: return None result: WeightedPath = [] # holds the final MST pq: PriorityQueue[WeightedEdge] = PriorityQueue() visited: [bool] = [False] * wg.vertex_count # where we've been def visit(index: int): visited[index] = True # mark as visited for edge in wg.edges_for_index(index): # add all edges coming from here to pq if not visited[edge.v]: pq.push(edge) visit(start) # the first vertex is where everything begins while not pq.empty: # keep going while there are edges to process edge = pq.pop() if visited[edge.v]: continue # don't ever revisit # this is the current smallest, so add it to solution result.append(edge) visit(edge.v) # visit where this connects return result
def a_star(maze, start, goal): pq = PriorityQueue() # In the A* trace we said that the F value for the initial cell position would be equal to # the H value...but we are not required to have to calculate that manually because there's only # going to be one item on the queue at this point, it will automatically # have the highest priority so we can set it equal to 0 pq.put(start, 0) predecessors = {start: None} g_values = {start: 0} # In our representation of these mazes, we have cells connected by edges and the weight # of each edge is just one. So the new cost is just one more than the previous cost # putting it in g values and in predecessors is equivalent to saying *we've discovered this while not pq.is_empty(): current_cell = pq.get() if current_cell == goal: return get_path(predecessors, start, goal) for direction in ["up", "right", "down", "left"]: row_offset, col_offset = offsets[direction] neighbour = (current_cell[0] + row_offset, current_cell[1] + col_offset) if is_legal_pos(maze, neighbour) and neighbour not in g_values: new_cost = g_values[current_cell] + 1 g_values[neighbour] = new_cost f_value = new_cost + heuristic(goal, neighbour) pq.put(neighbour, f_value) predecessors[neighbour] = current_cell return None
def trace_back(goal_node, start_node, v_distances, visited_nodes, n, mazearray, diags=False, visualise=VISUALISE): path = [goal_node] current_node = goal_node while current_node != start_node: neighbour_distances = PriorityQueue() neighbours = get_neighbours(current_node, n, diags) try: distance = v_distances[current_node] except Exception as e: print(e) for neighbour, ntype in neighbours: if neighbour in v_distances: distance = v_distances[neighbour] neighbour_distances.push(distance, neighbour) distance, smallest_neighbour = neighbour_distances.pop() mazearray[smallest_neighbour[0]][smallest_neighbour[1]].update(is_path=True) draw_square(smallest_neighbour[0],smallest_neighbour[1],grid=mazearray) path.append(smallest_neighbour) current_node = smallest_neighbour pygame.display.flip() mazearray[start_node[0]][start_node[1]].update(is_path=True)
def extract_sentences_ucs(graph, original_sentences): # uniform cost search pk = PriorityQueue() # (vertex, parent, accumulated cost) start = (graph.vert_dict[0], None, 0) end_position = len(graph.vert_dict) - 1 pk.insert(start, start[2]) visited = [start[0].position] current = None # finding path to last sentence while not pk.isEmpty(): current = pk.pop().data visited.append(current[0].position) if current[0].position == end_position: break for v, weigth in current[0].adjacent.items(): if v.position <= current[0].position: continue if v.position not in visited: cost = current[2] + abs(v.position - current[0].position)/(weigth * v.rank) pk.insert((v, current, cost), cost) # building path path = [] while current is not None: path.append(current[0]) current = current[1] path.reverse() sentences = list(original_sentences[v.position] for v in path) return sentences
def __init__(self, map: OccupancyGridMap, s_start: (int, int, int), s_goal: (int, int, int)): """ :param map: the ground truth map of the environment provided by gui :param s_start: start location :param s_goal: end location """ ## we need to also update our occupancy grid map self.new_edges_and_old_costs = None # algorithm start self.s_start = s_start # now takes in an x, y and z self.s_goal = s_goal # now takes in an x, y and z self.s_last = s_start # now takes in an x, y and z self.k_m = 0 # accumulation self.U = PriorityQueue() self.rhs = np.ones((map.x_dim, map.y_dim, map.z_dim)) * np.inf self.g = self.rhs.copy() self.sensed_map = OccupancyGridMap(x_dim=map.x_dim, y_dim=map.y_dim, z_dim=map.z_dim, exploration_setting='26N') self.rhs[self.s_goal] = 0 self.U.insert(self.s_goal, Priority(heuristic(self.s_start, self.s_goal), 0))
def test_assign_priority_via_insert(): new_pq = PriorityQueue() for i in range(5): new_pq.insert(Job(priority=i + 1)) new_pq.jobs[-1].time_created -= 100 new_pq.insert(Job(priority=6)) assert [job.priority for job in new_pq.jobs] == [8, 5, 6, 1, 4, 2]
def test_update(self): Q = PriorityQueue() Q.add_update(1, 2) Q.add_update(2, 1) Q.add_update(1, 0) self.assertEqual(Q.pop(), 1)
def test_sequence4(self): Q = PriorityQueue([1, 2, 3]) self.assertEqual(Q.extract_max(), 3) self.assertEqual(Q.extract_max(), 2) self.assertEqual(Q.extract_max(), 1) with self.assertRaises(NoMoreDataError): Q.extract_max()
def run_algorithm(self): """ run the algorithm :return: True is there is a path from strat to end, False otherwise """ open_list = PriorityQueue(f=self.f) open_list.append(self.start_point) closed_list = set() while not len(open_list) == 0: next_n = open_list.pop() closed_list.add(next_n) if self.end_point == next_n: self.value = next_n.total_value() self.path = next_n.arrived_from return True else: self.path_count += 1 for suc in next_n.successors: suc.arrived_from = next_n.arrived_from + [self.get_direction(next_n.x, next_n.y, suc.x, suc.y)] suc.fathers = next_n.fathers + [next_n] if suc not in closed_list and suc not in open_list: open_list.append(copy.deepcopy(suc)) elif suc in open_list and self.f(suc) < open_list[suc]: del open_list[suc] open_list.append(copy.deepcopy(suc)) self.path = self.NO_PATH return False
def test_pop_one_item_works(): test_pq = PriorityQueue() test_pq.insert(10, "test") assert test_pq.pop().val == 'test' with pytest.raises(IndexError) as error: test_pq.pop() assert 'The queue is empty' in str(error.value)
def dijkstra(wg: WeightedGraph[V], root: V) \ -> Tuple[List[Optional[float]], Dict[int, WeightedEdge]]: first: int = wg.index_of(root) # 出発点の index を見つける # 最初は距離は分からない distances: List[Optional[float]] = [None] * wg.vertex_count distances[first] = 0 path_dict: Dict[int, WeightedEdge] = {} # 各 vertex への行き方 pq: PriorityQueue[DijkstraNode] = PriorityQueue() pq.push(DijkstraNode(first, 0)) while not pq.empty: u: int = pq.pop().vertex # 次に近い vertex へ dist_u: float = distances[u] for we in wg.edges_for_index(u): # この vertex への古い距離 dist_v: float = distances[we.v] # 古い距離が無い、またはより短い path が見つかった場合 if dist_v is None or dist_v > we.weight + dist_u: # この vertex への距離を更新 distances[we.v] = we.weight + dist_u # この vertex への最短の path の edge を更新 path_dict[we.v] = we # 探索する pq.push(DijkstraNode(we.v, we.weight + dist_u)) return distances, path_dict
def __search(graph: Graph, start: Node, goal: Node): frontier = PriorityQueue() frontier.put(start, 0) came_from = {} cost_so_far = {} came_from[start] = None cost_so_far[start] = 0 while not frontier.empty(): current = frontier.get() if current == goal: break for next_node in graph.neighbours(current): new_cost = cost_so_far[current] + distance(current, next_node) if next_node not in cost_so_far or new_cost < cost_so_far[next_node]: cost_so_far[next_node] = new_cost priority = new_cost + distance(goal, next_node) # print("Priority: ", priority) # print("next_node: ", next_node.name()) frontier.put(next_node, priority) came_from[next_node] = current return came_from, cost_so_far
def best_first(game, heuristic): """ Create priority queue for all child fields of Rush Hour board, get first in first out. Check if field is unique, then call heuristic and append to queue. Heuristic 'cars to exit' counts the number of cars blocking the red car to the exit. Hueristic 'cars in traffic' counts the number of cars to move, before the red car can be moved. Return number of moves needed to solve the game and number of states checked. Keyword arguments: game -- RushHour object heuristic -- string containing heuristic to apply """ queue = PriorityQueue() moves = 0 states = 0 vehicles = list(game.vehicles.values()) queue.push([moves, vehicles], 0) while not game.won(vehicles): moves, vehicles = queue.get_prio() game.fill_field(vehicles) child_fields = game.get_child_fields_whole_step(vehicles) moves += 1 states += 1 print(moves) for field in child_fields: if game.is_unique(field): if heuristic == "cars_to_exit": priority = moves + game.cars_to_exit(field) elif heuristic == "cars_in_traffic": priority = moves + game.cars_in_traffic(field) queue.push([moves, field], priority) return moves, states
def __init__(self, app_list, pe_list): self.app_list = app_list # self.app_list = sorted(app_list, key=lambda _app: _app.priority) self.layer_list = [l for _app in app_list for l in _app.layer_list] self.layer_set = set(self.layer_list) self.gene2fit = {} # FIXME self.single_mode = False first_node = app_list[0].layer_list[0] if len(app_list) == 1 and first_node.get_index() != 0: self.single_mode = True self.num_layer = len(self.layer_list) self.throughput_thresh = 100 self.draw_iteration = 1 self.num_pe = len(pe_list) self.prio_step = len(self.layer_list) # Total number of layers self.pe_list = pe_list # variables for CPU utilization constraint self.elapsed_time_per_pe = [0] * self.num_pe self._ready_queues = [PriorityQueue() for _ in range(self.num_pe)] self._rq_set = set()
def test_not_empty(self): """ A queue with one enqueued value is not empty. """ pq = PriorityQueue() pq.enqueue(Job(1, 'People')) self.assertFalse(pq.is_empty())
def dijkstra(wg: WeightedGraph[V], root: V) -> Tuple[List[Optional[float]], Dict[int, WeightedEdge]]: first: int = wg.index_of(root) # find starting index # distances are unknown at first distances: List[Optional[float]] = [None] * wg.vertex_count distances[first] = 0 # the root is 0 away from the root path_dict: Dict[int, WeightedEdge] = {} # how we got to each vertex pq: PriorityQueue[DijkstraNode] = PriorityQueue() pq.push(DijkstraNode(first, 0)) while not pq.empty: u: int = pq.pop().vertex # explore the next closest vertex dist_u: float = distances[u] # should already have seen it # look at every edge/vertex from the vertex in question for we in wg.edges_for_index(u): # the old distance to this vertex dist_v: float = distances[we.v] # no old distance or found shorter path if dist_v is None or dist_v > we.weight + dist_u: # update distance to this vertex distances[we.v] = we.weight + dist_u # update the edge on the shortest path to this vertex path_dict[we.v] = we # explore it soon pq.push(DijkstraNode(we.v, we.weight + dist_u)) return distances, path_dict
def mst(wg: WeightedGraph[V], start: int = 0) -> Optional[WeightedPath]: if start > (wg.vertex_count - 1) or start < 0: return None result: WeightedPath = [] # содержит окончательное MST pq: PriorityQueue[WeightedEdge] = PriorityQueue() visited: [bool] = [False] * wg.vertex_count # здесь мы уже были def visit(index: int): visited[index] = True # пометить как прочитанное for edge in wg.edges_for_index(index): # добавляем все ребра отсюда в pq if not visited[edge.v]: pq.push(edge) visit(start) # первая вершина, с которой все начинается while not pq.empty: # продолжаем пока есть необработанные вершины edge = pq.pop() if visited[edge.v]: continue # чтобы никогда не просмотреть второй раз # на данный момент это минимальный вес, поэтому добавляем в дерево result.append(edge) # идем дальше visit(edge.v) return result