Example #1
0
def floyd_warshal(g: Graph):
    """
    the Floyd–Warshall algorithm is an algorithm for finding shortest paths in a weighted graph with positive
    or negative edge weights (but with no negative cycles). A single execution of the algorithm will find the
    lengths (summed weights) of the shortest paths between all pairs of vertices, though it does not return details
    of the paths themselves.
    Time complexity: O(V^3)
    """

    vertices_mapping = dict(zip(g.get_vertices(), count()))

    # Build V*V matrix initialized to sys.maxsize
    matrix = [[sys.maxsize] * len(vertices_mapping) for _ in range(len(vertices_mapping))]

    # Set distance to itself to zero
    for vertex in g.get_vertices():
        matrix[vertices_mapping[vertex]][vertices_mapping[vertex]] = 0

    # Set distance for all edges
    for vertex in g.get_vertices():
        for edge in g.get_outgoing_edges(vertex):
            succesive_vertex = edge.a if edge.a != vertex else edge.b
            matrix[vertices_mapping[vertex]][vertices_mapping[succesive_vertex]] = edge.weight

    # Main loop
    for k in g.get_vertices():
        for i in g.get_vertices():
            for j in g.get_vertices():
                matrix[vertices_mapping[i]][vertices_mapping[j]] = min(matrix[vertices_mapping[i]][vertices_mapping[k]] + \
                    matrix[vertices_mapping[k]][vertices_mapping[j]], matrix[vertices_mapping[i]][vertices_mapping[j]])

    return [(a, b, matrix[vertices_mapping[a]][vertices_mapping[b]]) for a in g.get_vertices() for b in g.get_vertices() if
            matrix[vertices_mapping[a]][vertices_mapping[b]] != sys.maxsize]
Example #2
0
def dijkstra(graph: Graph, start_node, end_node) -> (int, List):
    """
    Dijkstras shortest path algorithm implementation
    Works for directed and undirected graphs with non negative weights
    Time complexity: O(EV + V^2 * logV)
    :return Returns a tuple of the distance of the shortest path and the nodes to reach the shortest path
    """

    # Min heap
    pq = FibonacciHeap()
    pq.insert((0, start_node))

    # Final distances and paths from the start node
    distances = {key: sys.maxsize for key in graph.get_vertices()}
    paths = {key: [] for key in graph.get_vertices()}

    # Finished nodes
    visited_nodes = set()

    # Set start node distance to 0
    distances[start_node] = 0

    while not pq.is_empty():
        distance, vertex = pq.pop()

        if distance == sys.maxsize or end_node in visited_nodes:
            # Only unconnected vertices are left or we found the minimal distance
            break

        for outgoing_edge in graph.get_outgoing_edges(vertex):

            next_vertex = outgoing_edge.a if outgoing_edge.a != vertex else outgoing_edge.b

            if next_vertex in visited_nodes:
                continue

            if distance + outgoing_edge.weight < distances[next_vertex]:
                distances[next_vertex] = distance + outgoing_edge.weight
                paths[next_vertex] = paths[vertex] + [next_vertex]

                pq.insert((distance + outgoing_edge.weight, next_vertex))

        visited_nodes.add(vertex)

    return distances[end_node], paths[end_node]
Example #3
0
def dijkstra(graph: Graph, start_node, end_node) -> (int, List):
    """
    Dijkstras shortest path algorithm implementation
    Works for directed and undirected graphs with non negative weights
    Time complexity: O(EV + V^2 * logV)
    :return Returns a tuple of the distance of the shortest path and the nodes to reach the shortest path
    """

    # Min heap
    pq = FibonacciHeap()
    pq.insert((0, start_node))

    # Final distances and paths from the start node
    distances = {key: sys.maxsize for key in graph.get_vertices()}
    paths = {key: [] for key in graph.get_vertices()}

    # Finished nodes
    visited_nodes = set()

    # Set start node distance to 0
    distances[start_node] = 0

    while not pq.is_empty():
        distance, vertex = pq.pop()

        if distance == sys.maxsize or end_node in visited_nodes:
            # Only unconnected vertices are left or we found the minimal distance
            break

        for outgoing_edge in graph.get_outgoing_edges(vertex):

            next_vertex = outgoing_edge.a if outgoing_edge.a != vertex else outgoing_edge.b

            if next_vertex in visited_nodes:
                continue

            if distance + outgoing_edge.weight < distances[next_vertex]:
                distances[next_vertex] = distance + outgoing_edge.weight
                paths[next_vertex] = paths[vertex] + [next_vertex]

                pq.insert((distance + outgoing_edge.weight, next_vertex))

        visited_nodes.add(vertex)

    return distances[end_node], paths[end_node]
Example #4
0
def points_are_connected(graph: Graph, a, b, visited_points=None):
    if not visited_points:
        visited_points = set()

    if a == b:
        return True

    visited_points.add(a)

    for i in graph.get_successive_vertices(a):
        if i not in visited_points:
            if points_are_connected(graph, i, b, visited_points):
                return True
    return False
Example #5
0
def points_are_connected(graph:Graph, a, b, visited_points=None):
    if not visited_points:
        visited_points = set()

    if a == b:
        return True

    visited_points.add(a)

    for i in graph.get_successive_vertices(a):
        if i not in visited_points:
            if points_are_connected(graph, i, b, visited_points):
                return True
    return False
Example #6
0
def floyd_warshal(g: Graph):
    """
    the Floyd–Warshall algorithm is an algorithm for finding shortest paths in a weighted graph with positive
    or negative edge weights (but with no negative cycles). A single execution of the algorithm will find the
    lengths (summed weights) of the shortest paths between all pairs of vertices, though it does not return details
    of the paths themselves.
    Time complexity: O(V^3)
    """

    vertices_mapping = dict(zip(g.get_vertices(), count()))

    # Build V*V matrix initialized to sys.maxsize
    matrix = [[sys.maxsize] * len(vertices_mapping)
              for _ in range(len(vertices_mapping))]

    # Set distance to itself to zero
    for vertex in g.get_vertices():
        matrix[vertices_mapping[vertex]][vertices_mapping[vertex]] = 0

    # Set distance for all edges
    for vertex in g.get_vertices():
        for edge in g.get_outgoing_edges(vertex):
            succesive_vertex = edge.a if edge.a != vertex else edge.b
            matrix[vertices_mapping[vertex]][
                vertices_mapping[succesive_vertex]] = edge.weight

    # Main loop
    for k in g.get_vertices():
        for i in g.get_vertices():
            for j in g.get_vertices():
                matrix[vertices_mapping[i]][vertices_mapping[j]] = min(matrix[vertices_mapping[i]][vertices_mapping[k]] + \
                    matrix[vertices_mapping[k]][vertices_mapping[j]], matrix[vertices_mapping[i]][vertices_mapping[j]])

    return [(a, b, matrix[vertices_mapping[a]][vertices_mapping[b]])
            for a in g.get_vertices() for b in g.get_vertices()
            if matrix[vertices_mapping[a]][vertices_mapping[b]] != sys.maxsize]