Exemple #1
0
def show_graph(g: Graph):
    """
    Displays the graph g.
    :param g: the graph to display
    """
    vertices = g.vertices()
    edges = g.edges()

    dg = nx.DiGraph()
    dg.add_nodes_from(vertices, label=vertices)
    dg.add_weighted_edges_from([
        (edge._origin, edge._destination, edge.element()) for edge in edges
    ])

    plt.plot()
    layout = nx.circular_layout(dg)
    nx.draw(dg, layout, with_labels=True, connectionstyle='arc3, rad = 0.15')
    labels = nx.get_edge_attributes(dg, "weight")
    for key, weight in labels.items():
        labels[key] = round(labels[key], 2)
    nx.draw_networkx_edge_labels(dg,
                                 pos=layout,
                                 font_color='b',
                                 edge_labels=labels,
                                 label_pos=0.25,
                                 font_size=8)
    plt.show()
Exemple #2
0
def find_negative_cycle(
        graph: Graph, source: str) -> Tuple[bool, Optional[List[Graph.Edge]]]:
    """
    Finds a negative cycle starting at source in graph.
    :param graph: the graph where source is
    :param source: the starting node of the cycle to find
    :return:
        found: True if a negative cycle exists, False otherwise
        cycle: the list of edges representing the cycle. It is None if found is False.
    """
    # Step 1: Find all neighbors outgoing from source
    neighbors = {
        edge.opposite(source): edge
        for edge in graph.incident_edges(source, outgoing=True)
    }

    # Step 2: Find minimum edge weight in the graph
    minimum_edge_weight = min(edge.element() for edge in graph.edges())

    # Step 3: Make all edges positive
    for edge in graph.edges():
        edge._element += abs(minimum_edge_weight)

    # Step 4: Call compute_shortest_path from each vertex in neighbors to source
    paths = {
        vertex: compute_shortest_path(graph, vertex, source)
        for vertex in neighbors
    }

    # Step 5: Restore all edges weights
    for edge in graph.edges():
        edge._element -= abs(minimum_edge_weight)

    # Step 6: Close cycles
    for vertex, path in paths.items():
        if len(path) == 0:
            continue
        path_weight = sum(edge.element() for edge in path)
        first_edge = neighbors[vertex]
        first_weight = first_edge.element()
        cycle_weight = first_weight + path_weight
        cycle = [first_edge] + path
        if cycle_weight < 0:
            return True, cycle

    return False, None