Esempio n. 1
0
    class _Iterator:
        def __init__(self, root_node):
            self.root_node = root_node
            self.current_node = root_node
            self.queue = Queue_LinkedList()

            # Build the queue (default is from least node to greatest node)
            self.build_queue(self.current_node)

        def __next__(self):
            if self.queue.isEmpty() == True: raise StopIteration
            returned_node = self.queue.dequeue()
            return returned_node

        def build_queue(self, current_node):
            if current_node == None: return
            self.build_queue(current_node.left)
            self.queue.enqueue(current_node)
            #print(current_node.key)
            self.build_queue(current_node.right)
Esempio n. 2
0
class Shortest_Paths:
    def __init__(self, ewdg, s):
        self._distTo = [float('inf') for i in range(ewdg.V())]
        self._distTo[s] = 0

        self.edgeTo = [None] * ewdg.V()

        self.s = s

        self.vertex_queue = Queue_LinkedList()
        self.vertex_queue.enqueue(self.s)

        self.on_queue = [False] * ewdg.V()
        self.on_queue[self.s] = True

        self.cycle = None

        # Keeps track of the number of relax calls that are required in a pass
        # self.num_rcip = self.num_vaip after each pass
        self.num_rcip = 1
        # Keeps track of the number of edges that were eligible to be relaxed in the pass
        self.num_vaip = 0
        # Keeps track of the number of "passes" in the algorithm
        # When self.num_rcip reaches 0, we know we are starting a new "pass"
        self.pass_count = 1

        # some way of determining the order methodology of choosing v
        # In this case, we only look at edges coming from vertices that were relaxed in the previous pass instead of all of the edges as in sp_bellmanford_manual.
        print('Pass: '******'\n\n Negative cycle is reachable from s. Shortest paths cannot be computed.'
                )
                print(
                    '--------------------------------------------------------------------------------- \n\n'
                )
                self.findNegativeCycle()
                return

            v = self.vertex_queue.dequeue()
            self.on_queue[v] = False

            if self.num_rcip == 0:
                self.num_rcip = self.num_vaip
                self.num_vaip = 0
                self.pass_count += 1
                print('\n')
                print('Pass: '******'Queue is empty. Shortest paths for all reachable vertices from s have been found.'
        )
        print(
            '--------------------------------------------------------------------------------- \n\n'
        )

    def relax(self, ewdg, v):
        print("from vertex: ", v, " (removed from queue)")
        for edge in ewdg.adjacent(v):
            print('Edge: ', edge)
            v = edge.from_vert()
            w = edge.towards_vert()

            if self._distTo[v] + edge.weight() < self._distTo[w]:
                # number of vertices added on this relax
                self.num_vaip += 1

                print('This edge is eligible and will be relaxed')
                self.edgeTo[w] = edge

                self._distTo[w] = self._distTo[v] + edge.weight()
                print("towards vertex", w)
                if self.on_queue[w] == True:
                    print('The vertex ', w, ' is already on the queue')

                else:
                    print('The vertex ', w,
                          ' was not already on the queue. Added to queue.')
                    self.vertex_queue.enqueue(w)
                    self.on_queue[w] = True
            else:
                print('This edge is ineligible')

    def distTo(self, v):
        return self._distTo[v]

    def hasPathTo(self, v):
        return self._distTo[v] != float('inf')

    # Returns stack of directed edges from the source vertex s to a given vertex v.
    def pathTo(self, v):
        path_stack = Stack_ResizingArray()
        directed_edge = self.edgeTo[v]
        if v == self.s:
            return "No edges required to reach source vertex from source vertex"
        vert_from = directed_edge.from_vert()
        while vert_from != self.s:
            path_stack.push(directed_edge)
            directed_edge = self.edgeTo[vert_from]
            vert_from = directed_edge.from_vert()
        path_stack.push(directed_edge)
        return path_stack

    # This method is not required for the algorithm, I just added this to keep track of the number of "passes"
    def num_passes(self):
        return self.pass_count

    def hasNegativeCycle(self):
        return self.cycle is not None

    def findNegativeCycle(self):
        # Build ew_digraph from edges in edgeTo
        new_graph = Edge_Weighted_Digraph(V=len(self._distTo))
        for edge in self.edgeTo:
            # The entry for self.edgeTo[s] is None
            # Reminder that the 'is' and 'is not' operators test for reference/identity equality
            # In python, there is only one location for None in a python script, no matter how many variables are set to None
            # ie id(edge) == id(None)
            if edge is not None:
                new_graph.addEdge(edge)

        # We know there is a (negative) cycle in this ew_digraph
        cycle_finder = Directed_Weighted_Cycle(new_graph)
        self.cycle = cycle_finder.cycle()

    def negativeCycle(self):
        return self.cycle