def testGetMin(self): pq = PriorityQueue() randomTuples = self.generateRandomTuples(10000) for randomT in randomTuples: pq.insertNode(randomT) currentMin = pq.getMin() while len(pq.tree) > 1: nextMin = pq.getMin() self.assertLessEqual(currentMin[1], nextMin[1]) currentMin = nextMin
def lowerBoundImprovementReversed(source, target) : """ Evolution of the normal label-setting algorithm, with a preprocessing that uses Dijkstra bicriteria algorithm @return number of loops """ visitedNodes = __dijkstraBiCrit(target, source, 0) # safest path bestDanger = source.danger for v in visitedNodes: v.resetValue(True) __dijkstraBiCrit(target, source, 1) # shortest path bestDistance = source.distance labelQueue = PriorityQueue() sourceLabel = (0, 0, source, None, 0, None) source.labelList.append(sourceLabel) labelQueue.put(sourceLabel, sourceLabel[0]) ending = False counter = 0 while not labelQueue.isEmpty() : actualLabel = labelQueue.getMin() distSoFar = actualLabel[0] dangSoFar = actualLabel[1] actualNode = actualLabel[2] parentIndex = actualLabel[4] for nearNode, weight in actualNode.neighbors : distance, danger = weight ownIndex = len(nearNode.labelList) newLabel = (distSoFar + distance, dangSoFar + danger, nearNode, actualNode, ownIndex, parentIndex) # creating of a new label useLabel = True if nearNode.bestLabel[0] is not None and nearNode.bestLabel[1] is not None : # if the best label is present, enter checkDistance = newLabel[0] + nearNode.bestLabel[0] checkDanger = newLabel[1] + nearNode.bestLabel[1] if checkDanger >= bestDanger and checkDistance >= bestDistance : # if the values are negative is useless to check continue #checkLabel = (newLabel[0] + checkDistance, newLabel[1] + checkDanger) else : checkLabel = newLabel else : checkLabel = newLabel if ending : if isDominated(checkLabel, target.labelList) : # if the newlabel + bestLabel is dominated is useless go on continue # restart 'for' loop with another nearNode for label in nearNode.labelList : if isDominated(newLabel, [label]) : useLabel = False break # if a value is useless (1st case) the loop - label in labelList - is interrupt, to jump some loops if useLabel : nearNode.labelList.append(newLabel) if nearNode != target : labelQueue.put(newLabel, newLabel[0]) else : ending = True counter += 1 return counter
def a_star(source, target): listOfCand = PriorityQueue() listOfCand.put(source, 0) counter = 0 while not listOfCand.isEmpty(): actualNode = listOfCand.getMin() counter = counter + 1 actualNode.visited = True if target.visited: break for nextNode, distance in actualNode.neighbors: if not nextNode.visited: newDistance = actualNode.minWeight + distance[0] if newDistance < nextNode.minWeight: #this path is the best until now, let's record if nextNode.euclidean is None: # this check is to minimazie the calculation of the "euclidean distance" nextNode.euclidean = euclideanDistance( nextNode, target) nextNode.minWeight = newDistance nextNode.predecessor = actualNode priority = newDistance + nextNode.euclidean listOfCand.put(nextNode, priority) print("loops:", counter)
def __dijkstraBiCrit(source, target, alpha) : """ With the bicriteria algorithm I decided to use the attribute "distance" of the node, because "minWeight" is used has comparator. Also in normal dijkstra is calcolated the weight, in this specific case we know that the "weights" are distance and danger alpha : to varying of this variable the algorithm can find different results more α is near to 0, will be found the safest path more α is near to 1, will be found the shortest path """ visitedNodes = [] listOfCandidate = PriorityQueue() listOfCandidate.put(source, 0) while not listOfCandidate.isEmpty() : actualNode = listOfCandidate.getMin() actualNode.visited = True visitedNodes.append(actualNode) if target.visited : break for nextNode, weight in actualNode.neighbors : distance, danger = weight weightResult = alpha*distance + (1-alpha)*danger newWeight = actualNode.minWeight + weightResult if newWeight < nextNode.minWeight : nextNode.minWeight = newWeight nextNode.distance = actualNode.distance + distance nextNode.danger = actualNode.danger + danger nextNode.predecessor = actualNode listOfCandidate.put(nextNode, newWeight) if not isDominated((nextNode.distance, nextNode.danger), nextNode.bests) : for label in nextNode.bests : if label[0] > nextNode.distance and label[1] >= nextNode.danger : nextNode.bests.remove(label) nextNode.bests.append((nextNode.distance, nextNode.danger)) if alpha == 0 : # Those ifs are useful only with the lowerBound Algorithm () # if nextNode.bestLabel[1] is None or nextNode.bestLabel[1] > nextNode.danger : # nextNode.bestLabel[1] = nextNode.danger if nextNode.bestDangerLabel is None or nextNode.bestDangerLabel[1] > nextNode.danger : nextNode.bestDangerLabel = (nextNode.distance, nextNode.danger) elif alpha == 1 : # if nextNode.bestLabel[0] is None or nextNode.bestLabel[0] > nextNode.distance : # nextNode.bestLabel[0] = nextNode.distance if nextNode.bestDistanceLabel is None or nextNode.bestDangerLabel[0] > nextNode.distance : nextNode.bestDistanceLabel = (nextNode.distance, nextNode.danger) return visitedNodes
def dijkstra(self, start_label, end_label): start_vertex = self.find_vertex_by_label(start_label) start_vertex.weight = 0 pq = PriorityQueue() pq.build_heap(self.vertices) while not pq.isEmpty(): min_vertex = pq.getMin() # return Vertex object for neighbour_vertex in self.adjacencyList[min_vertex.label]: tmp_vertex = self.find_vertex_by_label( neighbour_vertex.label) # vertex object from self.vertices if min_vertex.weight + neighbour_vertex.weight < tmp_vertex.weight: tmp_vertex.parent = min_vertex.label tmp_vertex.weight = min_vertex.weight + neighbour_vertex.weight pq.deleteMin() print(self.print_path(end_label))
def dijkstraOneToAll(source): nodeSet = PriorityQueue() nodeSet.put(source, 0) # counter = 0 while not nodeSet.isEmpty(): actualNode = nodeSet.getMin() # counter = counter + 1 for nextNode, distance in actualNode.neighbors: newDistance = actualNode.minWeight + distance[0] if newDistance < nextNode.minWeight: #this is the better path, until now nextNode.minWeight = newDistance nextNode.predecessor = actualNode nodeSet.put(nextNode, newDistance) source.addShortestPath( nextNode, newDistance ) # all the path from the starting node are here
def dijkstraListOfCandidate(source, target): listOfCand = PriorityQueue() listOfCand.put(source, 0) while not listOfCand.isEmpty(): actualNode = listOfCand.getMin() actualNode.visited = True if target.visited: break for nextNode, distance in actualNode.neighbors: newDistance = actualNode.minWeight + distance[0] if newDistance < nextNode.minWeight: nextNode.minWeight = newDistance nextNode.predecessor = actualNode listOfCand.put(nextNode, newDistance) if not target.visited: # if the target is not been visited, it means that it wasn't in the set print("ERROR! impossible to reach the target")
def prim(self, start_label): start_vertex = self.find_vertex_by_label(start_label) start_vertex.weight = 0 pq = PriorityQueue() #for vertex in self.vertices: # pq.insert(vertex) pq.build_heap(self.vertices) while not pq.isEmpty(): min_vertex = pq.getMin() # return Vertex object if min_vertex.parent is not None: self.path += (min_vertex.parent + " -> " + min_vertex.label + ", ") for neighbour_vertex in self.adjacencyList[min_vertex.label]: tmp_vertex = self.find_vertex_by_label( neighbour_vertex.label) # vertex object from self.vertices if neighbour_vertex.weight < tmp_vertex.weight: tmp_vertex.parent = min_vertex.label tmp_vertex.weight = neighbour_vertex.weight pq.deleteMin() print(self.path)
def dijskstra(source): global dist global adjList pq = PriorityQueue() dist[source] = 0 pq.insertNode((source, 0)) while pq.getSize() > 1: currPair = pq.getMin() currNodeIndex = currPair[0] currWeight = currPair[1] if( currWeight > dist[currNodeIndex]): continue for neighbor in adjList[currNodeIndex]: nextNodeIndex = neighbor[0] nextWeight = neighbor[1] if dist[currNodeIndex] + nextWeight < dist[nextNodeIndex]: dist[nextNodeIndex] = dist[currNodeIndex] + nextWeight pq.insertNode(neighbor)
def labelSettingAlgorithm(source, target): """ label = (dist, danger, owner, predecessor, ownerListPos, predListPos) [0] [1] [2] [3] [4] [5] [ownerListPos] : is the position on the own label list [predListPos] : is the postion in the labelList of the predecessor label Step 0 : create first label (0, 0, source, null, 0, null) and put it in the labelSet (a priorityQueue) Step 1 : if labelSet.isEmpty() -> step 4 else select the label w/ the less distance and calc the label of the neighbors Step 2 : foreach neighbor of the current label calc What to do when i found a new label for a node : - 3 possibility 1st - new label IS DOMINATED by one already existence (in the node.labelList) -> delete new label 2nd - new label DOMINATE one or more already existence ( " " ) -> delete old label, add new label 3rd - new label ISN'T DOMINATED AND CAN'T DOMINATE any other node -> add new label Step 3 : return to Step 1 Step 4: End @return number of loops """ labelQueue = PriorityQueue() sourceLabel = (0, 0, source, None, 0, None) source.labelList.append(sourceLabel) labelQueue.put(sourceLabel, sourceLabel[0]) ending = False # become True when a "nearNode" is equal to the target counter = 0 while not labelQueue.isEmpty(): counter += 1 actualLabel = labelQueue.getMin() distSoFar = actualLabel[0] dangSoFar = actualLabel[1] actualNode = actualLabel[2] parentIndex = actualLabel[4] for nearNode, weight in actualNode.neighbors: distance, danger = weight ownIndex = len(nearNode.labelList) newLabel = (distSoFar + distance, dangSoFar + danger, nearNode, actualNode, ownIndex, parentIndex ) # creating of a new label useLabel = True if ending: # stop condition if isDominated(newLabel, target.labelList): continue # restart for loop if the new label is dominated for label in nearNode.labelList: if not __usableLabel(newLabel, label, nearNode.labelList): useLabel = False break # if a value is useless (1st case) the loop - label in labelList - is interrupt, to jump some loops if useLabel: nearNode.labelList.append(newLabel) if nearNode != target: labelQueue.put(newLabel, newLabel[0]) else: ending = True return counter