def test_basic_unweighted(graph): populate_test_graph(graph) paths_from_1 = shortest_path.compile(graph=graph, source=1) path_from_1_to_6 = [(x,y) for x,y in paths_from_1(target=6)] assert path_from_1_to_6 == [(1,2), (2,5), (5,6)] paths_to_6 = shortest_path.compile(graph=graph, target=6) path_to_6_from_1 = [(x,y) for x,y in paths_to_6(source=1)] assert path_to_6_from_1 == [(1,2), (2,5), (5,6)]
def test_exhaustive_unweighted(graph): populate_test_graph(graph) for u in graph.vertices(): for v in graph.vertices(): paths_from_u = shortest_path.compile(graph=graph, source=u) paths_to_v = shortest_path.compile(graph=graph, target=v) u_to_v_from_source = [(x,y) for x,y in paths_from_u(target=v)] u_to_v_to_target = [(x,y) for x,y in paths_to_v(source=u)] assert u_to_v_from_source == u_to_v_to_target
def test_basic_weighted_no_negative_edges(graph): populate_test_graph(graph) paths_from_1 = shortest_path.compile(graph=graph, source=1, edge_weight=graph.edge_weight) path_from_1_to_6 = [(x,y) for x,y in paths_from_1(target=6)] assert path_from_1_to_6 == [(1,2), (2,3), (3,4), (4,5), (5,6)] paths_to_6 = shortest_path.compile(graph=graph, target=6, edge_weight=graph.edge_weight) path_to_6_from_1 = [(x,y) for x,y in paths_to_6(source=1)] assert path_to_6_from_1 == [(1,2), (2,3), (3,4), (4,5), (5,6)]
def test_exhaustive_weighted_negative_edges(graph): populate_test_graph(graph) for e in graph.edges(source=3, target=4): graph.edge_weight[e] = -5 for u in graph.vertices(): for v in graph.vertices(): paths_from_u = shortest_path.compile(graph=graph, source=u, edge_weight=graph.edge_weight) paths_to_v = shortest_path.compile(graph=graph, target=v, edge_weight=graph.edge_weight) u_to_v_from_source = [(x,y) for x,y in paths_from_u(target=v)] u_to_v_to_target = [(x,y) for x,y in paths_to_v(source=u)] assert u_to_v_from_source == u_to_v_to_target
def test_basic_all_pairs(graph): populate_test_graph(graph) all_paths = shortest_path.compile(graph=graph) path_from_1_to_6 = [(x,y) for x,y in all_paths(source=1, target=6)] assert path_from_1_to_6 == [(1,2), (2,5), (5,6)] path_from_1_to_5 = [(x,y) for x,y in all_paths(source=1, target=5)] assert path_from_1_to_5 == [(1,2), (2,5)] path_from_2_to_6 = [(x,y) for x,y in all_paths(source=2, target=6)] assert path_from_2_to_6 == [(2,5), (5,6)] path_from_3_to_4 = [(x,y) for x,y in all_paths(source=3, target=4)] assert path_from_3_to_4 == [(3,4)]
def test_negative_weight_cycle(graph): populate_test_graph(graph) # (10,11) is on a cycle, so making its weight small enough makes the # cycle's weight negative # -2 isn't small enough, just makes the cycle weight 0 for edge in graph.edges(source=10, target=11): graph.edge_weight[edge] = -2 shortest_path.compile(graph=graph, edge_weight=graph.edge_weight, source=1) # -3 is small enough, but we shouldn't throw a NegativeCycleError unless the # source is in position to encounter the negative cycle. for edge in graph.edges(source=10, target=11): graph.edge_weight[edge] = -3 shortest_path.compile(graph=graph, edge_weight=graph.edge_weight, source=5) py.test.raises(NegativeCycleError, """ shortest_path.compile(graph=graph, edge_weight=graph.edge_weight, source=1) """)
def test_shortest_paths(graph): """ A tree T plus an edge_weight map W is a shortest path tree for graph G exactly when, for every edge e in G.edges(), sum(W[f] for f in T.path_to_root(e[0])) + W[e] >= sum(W[f] for f in T.path_to_root(e[1])) verify_shortest_path_tree tests this relationship. If there's an edge that violates this relationship, that edge is returned. Otherwise, None is returned. """ g = graph() edge_weight = getattr(g, 'edge_weight', None) ew = edge_weight if edge_weight is not None else defaultdict(int) for v in g.vertices(): sp = shortest_path.compile(graph=g, edge_weight=edge_weight, target=v) for e in g.edges(): assert sum(ew[f] for f in sp(source=e[0])) + ew[e] >= \ sum(ew[f] for f in sp(source=e[1]))