Example #1
0
class Directed_DFS_Orderings_EWD:
    def __init__(self, ew_digraph):
        self.ew_digraph = ew_digraph
        self.marked_array = [False] * self.ew_digraph.V()

        self.pre_order = Queue_LinkedList()
        self.post_order = Queue_LinkedList()
        self.reverse_post_order = Stack_ResizingArray()

        for i in range(self.ew_digraph.V()):
            if self.marked_array[i] != True:
                self.dfs(i)

    def dfs(self, v):
        self.pre_order.enqueue(v)
        self.marked_array[v] = True

        # For Edge_Weighted_Digraph, self.ew_digraph.adjacent(v) returns the edges coming from vertex v (in Digraph, self.digraph.adjacent(v) returns the vertices v is pointing towards).
        for directed_edge in self.ew_digraph.adjacent(v):
            w = directed_edge.towards_vert()
            if self.marked_array[w] != True:
                self.dfs(w)
        self.post_order.enqueue(v)
        self.reverse_post_order.push(v)

    def preorder(self):
        return self.pre_order

    def postorder(self):
        return self.post_order

    def reversepostorder(self):
        return self.reverse_post_order
class Directed_DFS_Orderings:
    def __init__(self, digraph):
        self.marked_array = [False] * digraph.V()

        self.pre_order = Queue_LinkedList()
        self.post_order = Queue_LinkedList()
        self.reverse_post_order = Stack_ResizingArray()

        for i in range(digraph.V()):
            if not self.marked_array[i]:
                self.dfs(i, digraph)

    def dfs(self, v, digraph):
        self.pre_order.enqueue(v)
        self.marked_array[v] = True
        for j in digraph.adjacent(v):
            if not self.marked_array[j]:
                self.dfs(j, digraph)
        self.post_order.enqueue(v)
        self.reverse_post_order.push(v)

    def preorder(self):
        return self.pre_order

    def postorder(self):
        return self.post_order

    def reversepostorder(self):
        return self.reverse_post_order
Example #3
0
        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)
Example #4
0
class MST_Kruskal:
    def __init__(self, ewg):
        self.mst_edges = Queue_LinkedList()
        self.edges_pq = PriorityQueue_Min_BinaryHeap()

        # Takes E*lg(E) time
        for edge in ewg.edges():
            self.edges_pq.insert(edge)
        # Note that we can construct a heap of size E in E time w/ heapq.heapify() (see algorithm for heap construction in heapsort)

        self.union_find = UF_WeightedQuickUnion(num_sites=ewg.V())

        # Takes E*(lg(E) + lg(V)) + (V-1)*lg(V) time which simplies to ~ E*lg(E) time
        while self.edges_pq and len(self.mst_edges) < (ewg.V() - 1):
            min_edge = self.edges_pq.delMin()
            # Before adding min_edge to self.mst_edges queue, need to confirm that adding this edge won't create a cycle:
            # Can do this by using Union Find data structure
            # If the two vertices are already connected in the union_find data structure, we know that adding an edge would create a cycle
            vertex_1 = min_edge.either()
            vertex_2 = min_edge.other(vertex_1)
            if not self.union_find.connected(vertex_1, vertex_2):
                self.mst_edges.enqueue(min_edge)
                self.union_find.union(vertex_1, vertex_2)

    # returns iterable of all edges in the MST b/c self.mst_edges is a queue (which is an iterable object)
    # Takes V-1 time
    def edges(self):
        return self.mst_edges

    # Takes V-1 time
    def weight(self):
        total_weight = 0
        for edge in self.mst_edges:
            total_weight += edge.weight()
        return total_weight
Example #5
0
    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 __init__(self, digraph):
        self.marked_array = [False] * digraph.V()

        self.pre_order = Queue_LinkedList()
        self.post_order = Queue_LinkedList()
        self.reverse_post_order = Stack_ResizingArray()

        for i in range(digraph.V()):
            if not self.marked_array[i]:
                self.dfs(i, digraph)
Example #7
0
    def __init__(self, ew_digraph):
        self.ew_digraph = ew_digraph
        self.marked_array = [False] * self.ew_digraph.V()

        self.pre_order = Queue_LinkedList()
        self.post_order = Queue_LinkedList()
        self.reverse_post_order = Stack_ResizingArray()

        for i in range(self.ew_digraph.V()):
            if self.marked_array[i] != True:
                self.dfs(i)
class MST_LazyPrim:
    def __init__(self, ewg):
        self.mst_vertices = [False] * ewg.V()
        self.mst_edges = Queue_LinkedList()
        self.crossing_edges = PriorityQueue_Min_BinaryHeap()

        self.visit(ewg, 0)
        while self.crossing_edges:
            min_weight_crossing_edge = self.crossing_edges.delMin()
            # Need to check for ineligible edges:
            vert_1 = min_weight_crossing_edge.either()
            vert_2 = min_weight_crossing_edge.other(vert_1)
            if self.mst_vertices[vert_1] and self.mst_vertices[vert_2]:
                continue
            else:
                self.mst_edges.enqueue(min_weight_crossing_edge)
                # Need to determine which vertex in min_weight_crossing_edge is not already in mst:
                if self.mst_vertices[vert_1]:
                    self.visit(ewg, vert_2)
                if self.mst_vertices[vert_2]:
                    self.visit(ewg, vert_1)

    def visit(self, ewg, vertex):
        # Add vertex to MST
        self.mst_vertices[vertex] = True

        # Add edges to verticies not currently in the MST
        # Note that some of the edges in the minPQ will become ineligible as more vertices are added to MST
        # These ineligible edges are non-mst edges connecting vertices already in MST
        for edge in ewg.adjacent(vertex):
            if not self.mst_vertices[edge.other(vertex)]:
                self.crossing_edges.insert(edge)

    # returns iterable of all edges in the MST
    def edges(self):
        return self.mst_edges

    def weight(self):
        total_weight = 0
        for edge in self.mst_edges:
            total_weight += edge.weight()
        return total_weight
Example #9
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)
    def __init__(self, ewg):
        self.mst_vertices = [False] * ewg.V()
        self.mst_edges = Queue_LinkedList()
        self.crossing_edges = PriorityQueue_Min_BinaryHeap()

        self.visit(ewg, 0)
        while self.crossing_edges:
            min_weight_crossing_edge = self.crossing_edges.delMin()
            # Need to check for ineligible edges:
            vert_1 = min_weight_crossing_edge.either()
            vert_2 = min_weight_crossing_edge.other(vert_1)
            if self.mst_vertices[vert_1] and self.mst_vertices[vert_2]:
                continue
            else:
                self.mst_edges.enqueue(min_weight_crossing_edge)
                # Need to determine which vertex in min_weight_crossing_edge is not already in mst:
                if self.mst_vertices[vert_1]:
                    self.visit(ewg, vert_2)
                if self.mst_vertices[vert_2]:
                    self.visit(ewg, vert_1)
Example #11
0
 def bfs(self, v, digraph):
     queue = Queue_LinkedList()
     queue.enqueue(v)
     while queue:
         v = queue.dequeue()
         for points_towards in digraph.adjacent(v):
             if not self.marked_array[points_towards]:
                 self.marked_array[points_towards] = True
                 self.paths_array[points_towards] = v
                 queue.enqueue(points_towards)
Example #12
0
 def bfs(self, graph, v):
     queue = Queue_LinkedList()
     self.marked_array[v] = True
     queue.enqueue(v)
     while queue:
         vertex = queue.dequeue()
         neighbors_list = graph.adj[vertex]
         for i in neighbors_list:
             if not self.marked_array[i]:
                 queue.enqueue(i)
                 self.marked_array[i] = True
                 self.path_array[i] = vertex
Example #13
0
 def __init__(self, ewdg, s):
     self.dist = [float('inf') for i in range(ewdg.V())]
     self.dist[s] = 0
     
     self.edgeTo = [None]*ewdg.V()
     
     self.queue = Queue_LinkedList()
     self.queue.enqueue(s) 
     
     self.on_queue = [False]*ewdg.V()
     self.on_queue[s] = True
     
     # keeps track of the # of edges from source to vertex in shortest path (should be a max of V-1, otherwise we have a negative cycle)
     self.len_path=[float('inf')]*ewdg.V()
     self.len_path[s]=0
     
     self.cycle = False
     self.s=s
     while self.queue:
         
         u = self.queue.dequeue()
         self.on_queue[u]=False
         
         for edge in ewdg.adjacent(u):
             v=edge.towards_vert()
             weight=edge.weight()
             if self.dist[u]+weight < self.dist[v]:
                 self.dist[v] = self.dist[u]+weight
                 self.len_path[v] = self.len_path[u]+1
                 if self.len_path[v] >= ewdg.V():
                     self.cycle=True
                     print('Negative cycle detected')
                     return
                 self.queue.enqueue(v)
                 self.on_queue[v]=True
                 self.edgeTo[v]=edge
    def bfs(self, graph, v):
        queue = Queue_LinkedList()
        queue.enqueue(v)

        while queue:
            v = queue.dequeue()
            # if the vertex has already been marked as true, this means that this vertex was placed on the queue twice which can only occur if there is a cycle
            if self._marked_array[v]:
                self.has_cycle = True
            self._marked_array[v] = True
            neighbors = graph.adjacent(v)
            for neighbor in neighbors:
                if not self._marked_array[neighbor]:
                    queue.enqueue(neighbor)
Example #15
0
 def bfs(self, graph, v):
     queue = Queue_LinkedList()
     queue.enqueue(v)
     
     while queue:
         v = queue.dequeue()
         if self._marked_array[v]:
             continue
         self._marked_array[v] = True
         
         self._id[v] = self._count
         neighbors = graph.adjacent(v)
     
         for neighbor in neighbors:
             if not self._marked_array[neighbor]:
                 queue.enqueue(neighbor)
Example #16
0
    def bfs(self, graph, v):
        queue = Queue_LinkedList()
        queue.enqueue(v)

        while queue:
            v = queue.dequeue()
            if self._marked_array[v]:
                continue
            self._marked_array[v] = True
            neighbors = graph.adjacent(v)
            for neighbor in neighbors:
                if (self._marked_array[neighbor]) and (neighbor !=
                                                       self.prev_vertex[v]):
                    self.has_cycle = True
                elif not self._marked_array[neighbor]:
                    queue.enqueue(neighbor)
                    self.prev_vertex[neighbor] = v
Example #17
0
    def bfs(self, graph, v):
        queue = Queue_LinkedList()
        queue.enqueue(v)

        while queue:
            v = queue.dequeue()

            for neighbor in graph.adjacent(v):
                if (self.marked_array[neighbor]) and (
                        self.biparite_array[neighbor]
                        == self.biparite_array[v]):
                    self._isBiparite = False

                elif not self.marked_array[neighbor]:
                    #self.previous_vertex_array[neighbor] = v
                    self.biparite_array[neighbor] = not self.biparite_array[v]
                    self.marked_array[neighbor] = True
                    queue.enqueue(neighbor)
 def keysThatMatch(self, pat):
     queue = Queue_LinkedList()
     self.wildcard_collect(node=self.root, pre="", pat=pat, queue=queue)
     return queue
Example #19
0
class Shortest_Paths:
    def __init__(self, ewdg, s):
        self.dist = [float('inf') for i in range(ewdg.V())]
        self.dist[s] = 0
        
        self.edgeTo = [None]*ewdg.V()
        
        self.queue = Queue_LinkedList()
        self.queue.enqueue(s) 
        
        self.on_queue = [False]*ewdg.V()
        self.on_queue[s] = True
        
        # keeps track of the # of edges from source to vertex in shortest path (should be a max of V-1, otherwise we have a negative cycle)
        self.len_path=[float('inf')]*ewdg.V()
        self.len_path[s]=0
        
        self.cycle = False
        self.s=s
        while self.queue:
            
            u = self.queue.dequeue()
            self.on_queue[u]=False
            
            for edge in ewdg.adjacent(u):
                v=edge.towards_vert()
                weight=edge.weight()
                if self.dist[u]+weight < self.dist[v]:
                    self.dist[v] = self.dist[u]+weight
                    self.len_path[v] = self.len_path[u]+1
                    if self.len_path[v] >= ewdg.V():
                        self.cycle=True
                        print('Negative cycle detected')
                        return
                    self.queue.enqueue(v)
                    self.on_queue[v]=True
                    self.edgeTo[v]=edge
            
            
        
    
    def distTo(self, v):
        return self.dist[v]
        
    def hasPathTo(self,v):
        return self.dist[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
    

    def hasNegativeCycle(self):
        return self.cycle
    
        
    def negativeCycle(self):
        return self.cycle
Example #20
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
Example #21
0
 def keys(self):
     queue = Queue_LinkedList()
     self.collect(node=self.root, pre="", queue=queue)
     return queue
Example #22
0
 def keysWithPrefix(self, pre):
     node = self._get(self.root, 0, pre)
     queue = Queue_LinkedList()
     self.collect(node=node.middle, pre=pre, queue=queue)
     return queue