예제 #1
0
def prim2(graph: GraphCore):
    pq = Heap()
    visited = set()
    src = next(iter(graph.vertices))
    visited.add(src)
    edges = set()
    for edge in graph.get_edges(src).items():
        dst, edge_props = edge
        weight = edge_props['weight']
        pq.push((weight, src, dst))
    while len(visited) != len(graph.vertices) and pq.size() > 0:
        top = pq.pop()
        while pq.size() > 0:
            weight, src, dst = top
            if dst not in visited:
                break
            top = pq.pop()
        visited.add(dst)
        edges.add(top)
        if len(visited) == len(graph.vertices):
            break
        src = dst
        for edge in graph.get_edges(src).items():
            dst, edge_props = edge
            weight = edge_props['weight']
            if dst not in visited:
                pq.push((weight, src, dst))
    return edges
예제 #2
0
def get_cycle_nodes(graph: GraphCore):
    '''
    1. Append all the vertices whose degree is 1 to a queue.
    2. Pop the queue front and mark it visited.
    3. Then decrement neighbours degree by 1. If it becomes 1, add neigh to queue.
    4. Repeat 2-3.
    5. Whichever nodes are not visited, they are in the cycle.
    '''
    degrees = {}
    que = deque()
    for src in graph.vertices:
        edges = graph.get_edges(src)
        degrees[src] = len(edges.keys())
        if degrees[src] == 1:
            que.append(src)

    visited = set()
    while que:
        front = que.popleft()
        assert (front not in visited)
        visited.add(front)
        neighbours = graph.get_edges(front).keys()
        for neigh in neighbours:
            degrees[neigh] -= 1
            if degrees[neigh] == 1:
                que.append(neigh)
    return graph.vertices - visited
def compute_longest_path_starting_at(graph: GraphCore, src, longest_distances):
    if src in longest_distances:
        return longest_distances[src]
    longest_path_distance = 1
    for neigh, edge_weight in graph.get_edges(src).items():
        longest_path_distance = max(
            longest_path_distance,
            compute_longest_path_starting_at(graph, neigh, longest_distances) +
            edge_weight["weight"],
        )
    longest_distances[src] = longest_path_distance
    return longest_path_distance
def longest_path_dag_topo(graph: GraphCore, src):
    """
    Single-Source Longest Path.
    Works even for negative edges!
    First get the topological sort order.
    Then in that order, do the following for every vertex 'curr':
    dist[neigh] = max(dist[neigh], dist[curr] + edge_weight).
    Complexity -> O(V+E)
    """
    topo_order = topo_sort(graph)
    assert (topo_order is not None)
    # distances[5] means the longest distance from node 'src' to node 5.
    distances = {}
    for vertex in graph.vertices:
        distances[vertex] = -inf
    distances[src] = 0
    for curr in topo_order:
        if distances[curr] == -inf:
            continue
        for neigh, edge_props in graph.get_edges(curr).items():
            weight = edge_props["weight"]
            distances[neigh] = max(distances[neigh], distances[curr] + weight)
    return distances
예제 #5
0
def prim(graph: GraphCore):
    '''
    1. Let current vertex `u` be vertices[0]. (Any random vertex)
    2. Add `u` to the MST vertices set `vertices_in_mst`.
    3. Add all the edges (u, v) to a heap for all v not already in MST.
    4. Find the lowest edge from heap such that the destination vertex `v` is not already in MST.
    5. Let this vertex `v` be the next vertex to process. Goto 1.
    6. Loop will end when MST set size === number of vertices.
    Complexity = O(ElogE)
    Kruskal is easier to implement and reason about!!
    '''
    edges_in_mst = []
    vertices_in_mst = set()
    # A heap containing the edges connecting MST with non-MST vertices.
    connecting_edges_pq = PriorityQueue()
    current_vertex = next(iter(graph.vertices))
    vertices_in_mst.add(current_vertex)
    while len(vertices_in_mst) < len(graph.vertices):
        vertex_edges = graph.get_edges(current_vertex)
        for dst, edge_props in vertex_edges.items():
            if dst in vertices_in_mst:
                continue
            connecting_edges_pq.put((edge_props["weight"], current_vertex,
                                     dst))
        lightest_edge = connecting_edges_pq.get()
        dst = lightest_edge[2]
        while dst in vertices_in_mst:
            # CAREFUL: Most important step.
            # Make sure to ignore all the vertices already processed.
            # Note: We wouldn't have needed this if we could somehow remove
            # all the edges (*, dst) from the heap efficiently.
            lightest_edge = connecting_edges_pq.get()
            dst = lightest_edge[2]
        edges_in_mst.append(lightest_edge)
        vertices_in_mst.add(dst)
        current_vertex = dst
    return edges_in_mst
예제 #6
0
def assign_component(src, graph_reverse: GraphCore, parent_mapping, root):
    if src in parent_mapping:
        return
    parent_mapping[src] = root
    for in_neigh in graph_reverse.get_edges(src):
        assign_component(in_neigh, graph_reverse, parent_mapping, root)
예제 #7
0
def visit(src, graph: GraphCore, visited, visit_order):
    visited.add(src)
    for neigh in graph.get_edges(src):
        if neigh not in visited:
            visit(neigh, graph, visited, visit_order)
    visit_order.append(src)