class KruskalsMST: def __init__(self, g): self.mst = [] self.g = g self.heap = MinHeap() self.UF = UnionFind(g.V) self.populateHeap() self.populate_mst() def populateHeap(self): edges = set() for i in range(self.g.V): for edge in self.g.adj(i): edges.add(edge) for edge in edges: self.heap.add_item(edge) def populate_mst(self): while len(self.mst) < self.g.V - 1 and not self.heap.is_empty(): edge = self.heap.del_min() if not self.UF.find(edge.either(), edge.other(edge.either())): self.mst.append(edge) self.UF.union(edge.either(), edge.other(edge.either())) def get_mst(self): return self.mst
def shortest_path(self, v_start, v_end): # item structure: {'w': 11, 'path': ['va', 'vb', ...]} priority_queue = MinHeap(criterion='w') # structure: {..., 'v_name': {'w': 11, 'path': ['va', 'vb',...] }} best_tracks = {} curr_track = {'path': [v_start], 'w': 0, 'v': v_start} while True: for edge in self.vertex_edges[curr_track['v']]: new_track = { 'w': curr_track['w'] + edge['w'], 'path': curr_track['path'] + [edge['v2']] } priority_queue.insert(new_track) assert priority_queue.is_empty() == False min_track = priority_queue.getMin() while better_track_exists(min_track, best_tracks): min_track = priority_queue.getMin() if at_destination(min_track, v_end): return min_track best_tracks[min_track['path'][-1]] = min_track curr_track = min_track.copy() curr_track['v'] = min_track['path'][-1]
class KruskalsMST: def __init__(self, g): self.mst = [] self.g = g self.heap = MinHeap() self.done = [False]*self.g.V self.populate_mst() def travel_node(self, node): self.done[node] = True for each in self.g.adj(node): self.heap.add_item(each) def populate_mst(self): self.travel_node(0) while len(self.mst) < self.g.V-1 and not self.heap.is_empty(): edge = self.heap.del_min() if not self.done[edge.either()] and self.done[edge.other(edge.either())]: self.travel_node(edge.either()) self.mst.append(edge) elif self.done[edge.either()] and not self.done[edge.other(edge.either())]: self.travel_node(edge.other(edge.either())) self.mst.append(edge) def get_mst(self): return self.mst
def dijkstra (source_vertex, vertices, edges): minheap = MinHeap("dist") for vertex in vertices: vertex.parent = vertex vertex.dist = 999999 minheap.push(vertex) minheap.update_key( minheap.find_index(vertices[0]), 0 ) while not minheap.is_empty(): vertex = minheap.pop() print(vertex.id, vertex.parent.id, vertex.dist) for dest_vertex, weight in edges[vertex]: if dest_vertex.dist > vertex.dist + weight: dest_vertex.parent = vertex minheap.update_key( minheap.find_index(dest_vertex), vertex.dist + weight )
def MST_prim2(self): #최종적으로 만들어질 MST mst = Graph() mst.add_vertex(self.vertex_num) #TV={} : MST 정점의 집합, 시작 노드부터 하나씩 채워나간다 TV = set() #w_list : 각 정점의 w 값을 담아두기 위한 배열 w_list = [None for _ in range(self.vertex_num)] #min heap에 w와 from을 가진 정점을 담아둔다 #heap 초기화 : w->inf, from->None h = MinHeap() for i in range(1, self.vertex_num): w_list[i] = math.inf h.push(Element(i, math.inf, None)) #시작 노드인 0은 w->0, from->None w_list[0] = 0 h.push(Element(0, 0, None)) while not h.is_empty(): #가중치가 가장 작은 에지 (from, v) : w #정보를 가진 정점 Element v v = h.pop() #TV에 정점을 추가 TV.add(v.v) #TE에 에지 추가 if v._from != None: mst.insert_edge(v.v, v._from, v.w) #TV에 정점이 추가되면 인접 정점 중 #트리 밖에 있는 정점에 대해 업데이트 시도 #u는 새로 추가된 정점 v에 인접한 정점 노드 u = self.adjacency_list[v.v] while u: #u가 트리 밖의 정점이고 #기존 w 값보다 w(u, v)이 작다면 업데이트 if u.vertex not in TV and u.weight < w_list[u.vertex]: #w_list 업데이트 w_list[u.vertex] = u.weight h.decrease_weight(Element(u.vertex, u.weight, v.v)) u = u.link return mst
def dijkstra(self, start): seen = set() heap = MinHeap() heap.push(start, start.val) seen.add(start) while not heap.is_empty(): top, priority = heap.pop() for name, edge_dist in top.neighbors.items(): tmp_distance = edge_dist + priority neighbor = self.nodes[name] if tmp_distance < neighbor.val: neighbor.parent = top neighbor.val = tmp_distance if neighbor in seen: heap.update_priority(neighbor, neighbor.val) else: heap.push(neighbor, neighbor.val)
def algorithm(P: NPuzzleInstance, name='ASTAR'): begin = time.now() open_heap = MinHeap() open_heap.push( P.initial_state, P.initial_state.get_total_cost() if name == 'ASTAR' else P.initial_state.greedy_value) cost_so_far = {P.initial_state: 0} father_of = {P.initial_state: None} while not open_heap.is_empty(): # print('heap size -> ' + str(len(open_heap.elements)), end='\r', flush=True) P.current_state = open_heap.pop() if P.is_solved(): P.spent_time = time.now() - begin solution = [] curr = P.current_state while curr: solution.append(curr) curr = father_of[curr] P.build_solution(list(reversed(solution))) return P for neighbor in P.neighbors(): if neighbor not in cost_so_far.keys( ) or P.current_state.greedy_value < cost_so_far[neighbor]: cost_so_far[neighbor] = P.current_state.greedy_value open_heap.push( neighbor, neighbor.get_total_cost() if name == 'ASTAR' else neighbor.greedy_value) father_of[neighbor] = State( P.current_state.matrix, P.current_state.greedy_value, P.current_state.heuristic_value if name == 'ASTAR' else 0) return None
def a_star_search(P: NPuzzleInstance, parents=[]): open_heap = MinHeap() open_heap.push(P.initial_state, P.initial_state.get_total_cost()) cost_so_far = { P.initial_state: 0 } father_of = { P.initial_state: None } while not open_heap.is_empty(): print('\theap size -> ' + str(len(open_heap.elements)), end='\r', flush=True) P.current_state = open_heap.pop() if P.is_solved(): solution = [] curr = P.current_state while father_of[curr]: solution.append(curr) curr = father_of[curr] solution.append(curr) return list(reversed(solution)) for neighbor in P.neighbors(): new_cost = P.current_state.greedy_value if neighbor not in cost_so_far.keys() or new_cost < cost_so_far[neighbor]: cost_so_far[neighbor] = new_cost open_heap.push(neighbor, neighbor.get_total_cost()) father_of[neighbor] = State( P.current_state.matrix, P.current_state.greedy_value, P.current_state.heuristic_value ) return None
def __init__(self, graph): self.__tree = [] self.__weight = 0 heap = MinHeap() for i in range(graph.get_node_nums()): adj = graph.iter_nodes(i) for edge in adj: if edge.orgin < edge.goal: heap.add(edge) union_find = UnionFind(graph.get_node_nums()) while not heap.is_empty() and len( self.__tree) < graph.get_node_nums() - 1: edge = heap.pop() if not union_find.is_connected(edge.orgin, edge.goal): self.__tree.append(edge) union_find.union(edge.orgin, edge.goal) for x in self.__tree: self.__weight += x.weight
def test_is_empty(): heap = MinHeap() assert heap.is_empty() heap.add_all([randrange(0, 1000) for _ in range(0, randrange(1, 100))])