def receiveTxt(): aa = FibHeap() ll = input().split(', ') nums = [] for item in ll: aa.insert(int(item)) nums.append(int(item)) return aa, nums
def randomTest(): a = FibHeap() nums = [] for i in range(randint(1, 100)): num = randint(-100, 100) a.insert(num) nums.append(num) return a, nums
def removeminimum(self): while True: (priority, item) = self.pq.get_nowait() if (priority, item) in self.removed: self.removed.discard((priority, item)) else: self.count -= 1 return FibHeap.Node(priority, item)
def removeminimum(self): while True: (priority, item) = heapq.heappop(self.pq) if (priority, item) in self.removed: self.removed.discard((priority, item)) else: self.count -= 1 return FibHeap.Node(priority, item)
def prim_mst(): def get_weight(a, b): return e_map.get(a + b) or e_map.get(b + a) possible_moves = FibHeap() vertex = vertexes[0] vertex.is_in_tree = True for adjacency in vertex.adjacency_list: possible_moves.push( get_weight(vertex.identifier, adjacency.identifier), (vertex, adjacency)) count = 1 while count != len(vertexes): best_move = possible_moves.pop().value first, second = best_move if first.is_in_tree ^ second.is_in_tree: count += 1 if first.is_in_tree: cursor = second else: cursor = first cursor.is_in_tree = True for adjacency in cursor.adjacency_list: possible_moves.push( get_weight(cursor.identifier, adjacency.identifier), (cursor, adjacency)) print(best_move) print('---')
class FibPQ(PQueue): def __init__(self): self.heap = FibHeap() def __len__(self): return self.heap.count def insert(self, node): return self.heap.insert(node) def minimum(self): return self.heap.minimum() def removeMinimum(self): return self.heap.removeMinimum() def decreaseKey(self, node, newPriority): return self.heap.decreaseKey(node, newPriority)
def priority_queue(name): if name == "heappq": return HeapPQ() elif name == "fibheap": return FibHeap() elif name == "fibpq": return FibPQ() elif name == "queuepq": return QueuePQ() else: raise ValueError("Unrecognized priorty queue implementation '%s'" % name)
def prim_mst(): def get_weight(a, b): return e_map.get(a + b) or e_map.get(b + a) possible_moves = FibHeap() vertex = vertexes[0] vertex.is_in_tree = True for adjacency in vertex.adjacency_list: possible_moves.push(get_weight(vertex.identifier, adjacency.identifier), (vertex, adjacency)) count = 1 while count != len(vertexes): best_move = possible_moves.pop().value first, second = best_move if first.is_in_tree ^ second.is_in_tree: count += 1 if first.is_in_tree: cursor = second else: cursor = first cursor.is_in_tree = True for adjacency in cursor.adjacency_list: possible_moves.push(get_weight(cursor.identifier, adjacency.identifier), (cursor, adjacency)) print(best_move) print('---')
class VertexDijkstraPlus(Vertex): heap = FibHeap() def __init__(self, identifier: str): super().__init__(identifier) self.distance = inf - 1 self.parent = VertexDijkstraPlus self.reference = VertexDijkstraPlus.heap.push(self.distance, self) def decrease(self, distance: int): self.distance = distance VertexDijkstraPlus.heap.decrease(self.reference, distance) def relax(self, edge_map: dict): for adjacency in self.adjacency_list: distance = self.distance + edge_map[self.identifier + adjacency.identifier] if distance < adjacency.distance: adjacency.distance = distance adjacency.parent = self adjacency.decrease(distance) def restore(self): self.distance = inf - 1 self.parent = VertexDijkstraPlus self.reference = VertexDijkstraPlus.heap.push(self.distance, self) @staticmethod def calculate(start_vertex: 'VertexDijkstraPlus', edge_map): start_vertex.decrease(0) while VertexDijkstraPlus.heap.min_node is not FibNode: cursor = VertexDijkstraPlus.heap.pop().value cursor.relax(edge_map) @staticmethod def output(start_vertex: 'VertexDijkstraPlus', vertexes: List['VertexDijkstraPlus'], matrix: List[List]): for vertex in vertexes: if vertex is not start_vertex: matrix[int(start_vertex.identifier) - 1][int(vertex.identifier) - 1] = vertex.parent vertex.restore()
class FibPQ(PriorityQueue): def __init__(self): self.heap = FibHeap() def __len__(self): return self.heap.count def insert(self, node): self.heap.insert(node) def minimum(self): return self.heap.minimum() def removeminimum(self): return self.heap.removeminimum() def decreasekey(self, node, new_priority): self.heap.decreasekey(node, new_priority)
from FibonacciHeap import FibHeap from DenseGraph import DGraph if __name__ == "__main__": graph = DGraph() size = input() for i in range(int(size)): u, v, weight = input().split() graph.AddVertex(u) graph.AddVertex(v) graph.AddEdge(u, v, float(weight)) src = input().strip() tar = input().strip() fibHeap = FibHeap() heapNodeIndex = {} dist = {} prev = {} visited = {} for node in graph.vertices: if node == src: dist[node] = 0.0 prev[node] = None visited[node] = True heapNodeIndex[node] = fibHeap.insert(0.0, node) else: dist[node] = float('inf') prev[node] = None visited[node] = False heapNodeIndex[node] = fibHeap.insert(float('inf'), node)
def a_star(to_solve: maze.Maze) -> list: """Uses the A* search algorithm (variant of Dijkstra's algorithm) to solve a maze, 'maze'. Note that due to the way some mazes are structured -- very dense mazes with short paths -- A* may not outperform a breadth-first search, and in fact may be almost identical in its operation with extra computational overhead. However, this depends on the variety of maze supplied""" # get our start and end nodes start = to_solve.get_start() end = to_solve.get_end() # we will use the start and end positions so frequently that it is worth having variables for them; calling a # function is not free, so this trades off a little memory in exchange for a little better performance start_pos = start.get_position() end_pos = end.get_position() # set up our "visited" dictionary, like we have for BFS and DFS visited = {} # set up our priority queues # the unvisited list will be a Heap Priority Queue; the nodes we want to visit will be ordered according to the # heuristics we set for them -- get_distance from current node + Euclidian get_distance to end coordinate unvisited = HeapPQ( ) # we can use any priority queue, but I have found HeapPQ to be the fastest for this purpose start_node = FibHeap.Node(0, start) unvisited.insert(start_node) # we start with the start node unvisited # we also need an object to equate nodes from the Maze object with nodes from the FibHeap object node_index = {} node_index[start_pos] = start_node # the distances of all nodes start at infinity, because we haven't visited them yet and we don't know what the # get_distance is given the best known path infinity = float("inf") # track the get_distance to a given node using the best path known so far; better paths will replace worse ones as # we go. Note, however that this will NOT include the additional heuristic of the get_distance from the point to the # end position -- that information is included in the FibHeap node (we don't care about this additional heuristic # when we aren't adding new ones to the queue) distances = {} # the get_distance associated with S is 0 distances[start_pos] = 0 # track the number of considered nodes and whether we have completed the maze node_count = 0 completed = False # as long as we have nodes to visit, continue working while not completed and len(unvisited) > 0: node_count += 1 # get the node with the minimum combined heuristic and explore that first node = unvisited.remove_minimum() current = node.value # get the Maze.Node object current_pos = current.get_position() # if we are at the end, we have completed the maze; however, we can't exit just yet -- we need to wait until the # queue is empty to be sure we have found the best solution if current_pos == end_pos: completed = True # otherwise, check each unvisited child node, as in the breadth-first search else: # get our node's neighbors, and check each of them neighbors = [ current.neighbors[maze.Direction.NORTH], current.neighbors[maze.Direction.SOUTH], current.neighbors[maze.Direction.EAST], current.neighbors[maze.Direction.WEST] ] for child in neighbors: # if there is a neighbor at that position that we have not visited check it; otherwise, continue on if child is not None and child.get_position() not in visited: # get the positions so we can calculate our distances parent_pos = current_pos child_pos = child.get_position() # get the get_distance of parent to child parent_to_child = get_distance(parent_pos, child_pos) # we also want to know the get_distance to this child without our additional heuristic of the get # distance to the end node -- just the get_distance to the parent plus parent_to_child path_length = distances[parent_pos] + parent_to_child # get the get_distance of child to end -- this is our additional heuristic remaining_distance = get_distance(child_pos, end_pos) # if we have a get_distance associated with the node, fetch it; otherwise, it's infinity if child_pos in distances: current_distance = distances[child_pos] else: current_distance = infinity # We will only update the get_distance if path length is less than the get_distance currently # associated with this node's position -- if it's not, then the other path we have found to this # node is shorter, and so we shouldn't make any changes in the path to that node if path_length < current_distance: # if we have a node for the child already, update it; otherwise, create a new node for the child if child_pos in node_index: # we want to decrease the get_distance heuristic of the child node; but first, we need to # fetch the node from node_index, as decrease_key operates on a FibHeap.Node object to_decrease = node_index[child_pos] # the key is the coordinate, the new value is the path length plus the extra heuristic unvisited.decrease_key( to_decrease, path_length + remaining_distance) # update the get_distance to this node as well -- we have found a shorter path; again, this # does not include the additional heuristic distances[child_pos] = path_length # we also need to update the new parent node of that child child.parent = current # if we don't have a node for the child yet, create one else: # create a FibHeap node and add it to our priority queue new_node = FibHeap.Node( path_length + remaining_distance, child) node_index[child_pos] = new_node unvisited.insert(new_node) # update the entry at the get_distance vector for the child and make sure we mark the # current node as its previous node distances[child_pos] = path_length child.parent = current # add this node to "visited" so we don't try to evaluate it again visited[current_pos] = True # in the same manner as in in the BFS algorithm, construct the path by going back through the parent of each node, # starting at the end node and working backwards if completed: path = deque() current = end while current is not None: path.appendleft(current.get_position( )) # has a complexity of O(1) at each end, so do this instead of current = current.parent # appending to a list and reversing it at the end else: path = [] # we must return (bool)solved, (int)node_count, (list< tuple< int, int > >)path return completed, node_count, path
from FibonacciHeap import FibHeap get_input = False if __name__ == '__main__': graph = {} nodes = [] fibNodeList = {} fh = FibHeap() pred = dict() if get_input: print('Begin') edge_num = int(input()) if get_input: print(edge_num) for i in range(edge_num): x, y, w = input().split() if get_input: print(str(x) + ' ' + str(y) + ' ' + str(w)) if x not in graph: graph[x] = {} graph[x][y] = int(w) nodes.append(x) nodes.append(y) if get_input: print('Finish graph') start_point = input() if get_input:
def minimum(self): priority, item = heapq.heappop(self.pq) node = FibHeap.Node(priority, item) self.insert(node) return node
def __init__(self): self.heap = FibHeap()
def solve(maze): width = maze.width total = maze.width * maze.height start = maze.start startpos = start.Position end = maze.end endpos = end.Position visited = [False] * total prev = [None] * total infinity = float("inf") distances = [infinity] * total # You can change what kind of priority queues you wish to use. # unvisited = FibHeap() unvisited = HeapPQ() # unvisited = FibPQ() # unvisited = QueuePQ() nodeindex = [None] * total distances[start.Position[0] * width + start.Position[1]] = 0 startnode = FibHeap.Node(0, start) nodeindex[start.Position[0] * width + start.Position[1]] = startnode unvisited.insert(startnode) count = 0 completed = False while len(unvisited) > 0: count += 1 n = unvisited.removeminimum() u = n.value upos = u.Position uposindex = upos[0] * width + upos[1] if distances[uposindex] == infinity: break if upos == endpos: completed = True break for v in u.Neighbours: if v != None: vpos = v.Position vposindex = vpos[0] * width + vpos[1] if visited[vposindex] == False: d = abs(vpos[0] - upos[0]) + abs(vpos[1] - upos[1]) newdistance = distances[uposindex] + d remaining = abs(vpos[0] - endpos[0]) + abs(vpos[1] - endpos[1]) if newdistance < distances[vposindex]: vnode = nodeindex[vposindex] if vnode == None: vnode = FibHeap.Node(newdistance + remaining, v) unvisited.insert(vnode) nodeindex[vposindex] = vnode distances[vposindex] = newdistance prev[vposindex] = u else: unvisited.decreasekey(vnode, newdistance + remaining) distances[vposindex] = newdistance prev[vposindex] = u visited[uposindex] = True from collections import deque path = deque() current = end while (current != None): path.appendleft(current) current = prev[current.Position[0] * width + current.Position[1]] return [path, [count, len(path), completed]]
def AStar_Lat(start, goal, neighbor_nodes, distance, cost_estimate, weights): width, height = 512, 512 def idx(pos): return pos[1] * width + pos[0] total_size = width * height infinity = float("inf") distances = [infinity] * total_size visited = [False] * total_size prev = [None] * total_size unvisited = HeapPQ() node_index = [None] * total_size distances[idx(start)] = 0 start_node = FibHeap.Node(0, start) node_index[idx(start)] = start_node unvisited.insert(start_node) count = 0 aa = 0 ## to make sure not get too long roots completed = False plant_id = -1 final_goal_position = None while len(unvisited) > 0: n = unvisited.removeminimum() upos = n.value uposindex = idx(upos) if distances[uposindex] == infinity: break if upos in goal: completed = True #plant_id = goal[upos] final_goal_position = upos print(final_goal_position) break for v in neighbor_nodes(upos): vpos = v[0] vposindex = idx(vpos) if is_blocked_edge(vpos): continue if visited[vposindex]: continue # Calculate distance to travel to vpos d = weights[vpos[1], vpos[0]] new_distance = distances[uposindex] + d * v[1] if new_distance < distances[vposindex]: aa = distances[vposindex] vnode = node_index[vposindex] if vnode is None: vnode = FibHeap.Node(new_distance, vpos) unvisited.insert(vnode) node_index[vposindex] = vnode distances[vposindex] = new_distance prev[vposindex] = upos aa = distances[vposindex] else: unvisited.decreasekey(vnode, new_distance) distances[vposindex] = new_distance prev[vposindex] = upos aa = distances[vposindex] visited[uposindex] = True if completed and aa <= 200: from collections import deque path = deque() current = final_goal_position while current is not None: path.appendleft(current) current = prev[idx(current)] return path else: return []
def solve(maze): width = maze.width total = maze.width * maze.height start = maze.start startpos = start.Position end = maze.end endpos = end.Position visited = [False] * total prev = [None] * total infinity = float("inf") distances = [infinity] * total # The priority queue. There are multiple implementations in priority_queue.py # unvisited = FibHeap() unvisited = HeapPQ() # unvisited = FibPQ() # unvisited = QueuePQ() nodeindex = [None] * total distances[start.Position[0] * width + start.Position[1]] = 0 startnode = FibHeap.Node(0, start) nodeindex[start.Position[0] * width + start.Position[1]] = startnode unvisited.insert(startnode) count = 0 completed = False while len(unvisited) > 0: count += 1 n = unvisited.removeminimum() u = n.value upos = u.Position uposindex = upos[0] * width + upos[1] if distances[uposindex] == infinity: break if upos == endpos: completed = True break for v in u.Neighbours: if v != None: vpos = v.Position vposindex = vpos[0] * width + vpos[1] if visited[vposindex] == False: d = abs(vpos[0] - upos[0]) + abs(vpos[1] - upos[1]) # New path cost to v is distance to u + extra. Some descriptions of A* call this the g cost. # New distance is the distance of the path from the start, through U, to V. newdistance = distances[uposindex] + d # A* includes a remaining cost, the f cost. In this case we use manhattan distance to calculate the distance from # V to the end. We use manhattan again because A* works well when the g cost and f cost are balanced. # https://en.wikipedia.org/wiki/Taxicab_geometry remaining = abs(vpos[0] - endpos[0]) + abs(vpos[1] - endpos[1]) # Notice that we don't include f cost in this first check. We want to know that the path *to* our node V is shortest if newdistance < distances[vposindex]: vnode = nodeindex[vposindex] if vnode == None: # V goes into the priority queue with a cost of g + f. So if it's moving closer to the end, it'll get higher # priority than some other nodes. The order we visit nodes is a trade-off between a short path, and moving # closer to the goal. vnode = FibHeap.Node(newdistance + remaining, v) unvisited.insert(vnode) nodeindex[vposindex] = vnode # The distance *to* the node remains just g, no f included. distances[vposindex] = newdistance prev[vposindex] = u else: # As above, we decrease the node since we've found a new path. But we include the f cost, the distance remaining. unvisited.decreasekey(vnode, newdistance + remaining) # The distance *to* the node remains just g, no f included. distances[vposindex] = newdistance prev[vposindex] = u visited[uposindex] = True from collections import deque path = deque() current = end while (current != None): path.appendleft(current) current = prev[current.Position[0] * width + current.Position[1]] return [path, [count, len(path), completed]]
def solve(maze): width = maze.width # Used for indexing total = maze.width * maze.height # Array sizes start = maze.start # Start node startPos = start.Position end = maze.end # End node endPos = end.Position visited = [False ] * total # True/False wether a node has already been visited prev = [ None ] * total # Holds a link to the previous node in the path (used for path construction) infinity = float("inf") # Holds the max value of a float. distances = [ infinity ] * total # Default value of every node in the graph is infinity # unvisited = FibHeap() # We chose the Fibonnaci Heap for Dijkstra # Can also be one of the following priority queue # unvisited = FibPQ() unvisited = HeapPQ() # unvisited = QueuePQ() nodeIndex = [None] * total # Holds all priority queue nodes distances[ start.Position[0] * width + start.Position[1]] = 0 # Position[0] holds Y and Position[1] holds X startNode = FibHeap.Node(0, start) nodeIndex[start.Position[0] * width + start.Position[1]] = startNode unvisited.insert(startNode) count = 0 # Zero nodes visited completed = False # Not completed yet while len(unvisited) > 0: count += 1 n = unvisited.removeMinimum() current = n.value curPos = current.Position curPosIndex = curPos[0] * width + curPos[1] if distances[curPosIndex] == infinity: break if curPos == endPos: completed = True break for v in current.Neighbours: if v != None: vPos = v.Position vPosIndex = vPos[0] * width + vPos[1] if visited[vPosIndex] == False: manDist = abs(vPos[0] - curPos[0]) + abs(vPos[1] - curPos[1]) newDistance = distances[curPosIndex] + manDist if newDistance < distances[vPosIndex]: vNode = nodeIndex[vPosIndex] if vNode == None: vNode = FibHeap.Node(newDistance, v) unvisited.insert(vNode) nodeIndex[vPosIndex] = vNode distances[vPosIndex] = newDistance prev[vPosIndex] = current else: unvisited.decreaseKey(vNode, newDistance) distances[vPosIndex] = newDistance prev[vPosIndex] = current visited[curPosIndex] = True from collections import deque path = deque() current = end while current != None: path.appendleft(current) current = prev[current.Position[0] * width + current.Position[1]] return [path, [count, len(path), completed]]
def solve(maze): # Width is used for indexing, total is used for array sizes width = maze.width total = maze.width * maze.height # Start node, end node start = maze.start startpos = start.Position end = maze.end endpos = end.Position # Visited holds true/false on whether a node has been seen already. Used to stop us returning to nodes multiple times visited = [False] * total # Previous holds a link to the previous node in the path. Used at the end for reconstructing the route prev = [None] * total # Distances holds the distance to any node taking the best known path so far. Better paths replace worse ones as we find them. # We start with all distances at infinity infinity = float("inf") distances = [infinity] * total # The priority queue. We are using a Fibonacci heap in this case. unvisited = FibHeap() # This index holds all priority queue nodes as they are created. We use this to decrease the key of a specific node when a shorter path is found. # This isn't hugely memory efficient, but likely to be faster than a dictionary or similar. nodeindex = [None] * total # To begin, we set the distance to the start to zero (we're there) and add it into the unvisited queue distances[start.Position[0] * width + start.Position[1]] = 0 startnode = FibHeap.Node(0, start) nodeindex[start.Position[0] * width + start.Position[1]] = startnode unvisited.insert(startnode) # Zero nodes visited, and not completed yet. count = 0 completed = False # Begin Dijkstra - continue while there are unvisited nodes in the queue while unvisited.count > 0: count += 1 # Find current shortest path point to explore n = unvisited.minimum() unvisited.removeminimum() # Current node u, all neighbours will be v u = n.value upos = u.Position uposindex = upos[0] * width + upos[1] if distances[uposindex] == infinity: break # If upos == endpos, we're done! if upos == endpos: completed = True break for v in u.Neighbours: if v != None: vpos = v.Position vposindex = vpos[0] * width + vpos[1] if visited[vposindex] == False: # The extra distance from where we are (upos) to the neighbour (vpos) - this is manhattan distance # https://en.wikipedia.org/wiki/Taxicab_geometry d = abs(vpos[0] - upos[0]) + abs(vpos[1] - upos[1]) # New path cost to v is distance to u + extra newdistance = distances[uposindex] + d # If this new distance is the new shortest path to v if newdistance < distances[vposindex]: vnode = nodeindex[vposindex] # v isn't already in the priority queue - add it if vnode == None: vnode = FibHeap.Node(newdistance, v) unvisited.insert(vnode) nodeindex[vposindex] = vnode distances[vposindex] = newdistance prev[vposindex] = u # v is already in the queue - decrease its key to re-prioritise it else: unvisited.decreasekey(vnode, newdistance) distances[vposindex] = newdistance prev[vposindex] = u visited[uposindex] = True # We want to reconstruct the path. We start at end, and then go prev[end] and follow all the prev[] links until we're back at the start from collections import deque path = deque() current = end while (current != None): path.appendleft(current) current = prev[current.Position[0] * width + current.Position[1]] return [path, [count, len(path), completed]]
def minimum(self): (priority, item) = self.pq.get_nowait() node = FibHeap.Node(priority, item) self.insert(node) return node