1 #!/usr/bin/env python 2 from nose.tools import * 3 import networkx as nx 4 5 class TestWeightedPath: 6 7 def setUp(self): 8 from networkx import convert_node_labels_to_integers as cnlti 9 self.grid=cnlti(nx.grid_2d_graph(4,4),first_label=1,ordering="sorted") 10 self.cycle=nx.cycle_graph(7) 11 self.directed_cycle=nx.cycle_graph(7,create_using=nx.DiGraph()) 12 self.XG=nx.DiGraph() 13 self.XG.add_weighted_edges_from([('s','u',10) ,('s','x',5) , 14 ('u','v',1) ,('u','x',2) , 15 ('v','y',1) ,('x','u',3) , 16 ('x','v',5) ,('x','y',2) , 17 ('y','s',7) ,('y','v',6)]) 18 self.MXG=nx.MultiDiGraph(self.XG) 19 self.MXG.add_edge('s','u',weight=15) 20 self.XG2=nx.DiGraph() 21 self.XG2.add_weighted_edges_from([[1,4,1],[4,5,1], 22 [5,6,1],[6,3,1], 23 [1,3,50],[1,2,100],[2,3,100]]) 24 25 self.XG3=nx.Graph() 26 self.XG3.add_weighted_edges_from([ [0,1,2],[1,2,12], 27 [2,3,1],[3,4,5], 28 [4,5,1],[5,0,10] ]) 29 30 self.XG4=nx.Graph() 31 self.XG4.add_weighted_edges_from([ [0,1,2],[1,2,2], 32 [2,3,1],[3,4,1], 33 [4,5,1],[5,6,1], 34 [6,7,1],[7,0,1] ]) 35 self.MXG4=nx.MultiGraph(self.XG4) 36 self.MXG4.add_edge(0,1,weight=3) 37 self.G=nx.DiGraph() # no weights 38 self.G.add_edges_from([('s','u'), ('s','x'), 39 ('u','v'), ('u','x'), 40 ('v','y'), ('x','u'), 41 ('x','v'), ('x','y'), 42 ('y','s'), ('y','v')]) 43 44 def test_dijkstra(self): 45 (D,P)= nx.single_source_dijkstra(self.XG,'s') 46 assert_equal(P['v'], ['s', 'x', 'u', 'v']) 47 assert_equal(D['v'],9) 48 49 assert_equal(nx.single_source_dijkstra_path(self.XG,'s')['v'], 50 ['s', 'x', 'u', 'v']) 51 assert_equal(nx.single_source_dijkstra_path_length(self.XG,'s')['v'],9) 52 53 assert_equal(nx.single_source_dijkstra(self.XG,'s')[1]['v'], 54 ['s', 'x', 'u', 'v']) 55 56 assert_equal(nx.single_source_dijkstra_path(self.MXG,'s')['v'], 57 ['s', 'x', 'u', 'v']) 58 59 GG=self.XG.to_undirected() 60 # make sure we get lower weight 61 # to_undirected might choose either edge with weight 2 or weight 3 62 GG['u']['x']['weight']=2 63 (D,P)= nx.single_source_dijkstra(GG,'s') 64 assert_equal(P['v'] , ['s', 'x', 'u', 'v']) 65 assert_equal(D['v'],8) # uses lower weight of 2 on u<->x edge 66 assert_equal(nx.dijkstra_path(GG,'s','v'), ['s', 'x', 'u', 'v']) 67 assert_equal(nx.dijkstra_path_length(GG,'s','v'),8) 68 69 assert_equal(nx.dijkstra_path(self.XG2,1,3), [1, 4, 5, 6, 3]) 70 assert_equal(nx.dijkstra_path(self.XG3,0,3), [0, 1, 2, 3]) 71 assert_equal(nx.dijkstra_path_length(self.XG3,0,3),15) 72 assert_equal(nx.dijkstra_path(self.XG4,0,2), [0, 1, 2]) 73 assert_equal(nx.dijkstra_path_length(self.XG4,0,2), 4) 74 assert_equal(nx.dijkstra_path(self.MXG4,0,2), [0, 1, 2]) 75 assert_equal(nx.single_source_dijkstra(self.G,'s','v')[1]['v'], 76 ['s', 'u', 'v']) 77 assert_equal(nx.single_source_dijkstra(self.G,'s')[1]['v'], 78 ['s', 'u', 'v']) 79 80 assert_equal(nx.dijkstra_path(self.G,'s','v'), ['s', 'u', 'v']) 81 assert_equal(nx.dijkstra_path_length(self.G,'s','v'), 2) 82 83 # NetworkXError: node s not reachable from moon 84 assert_raises(nx.NetworkXNoPath,nx.dijkstra_path,self.G,'s','moon') 85 assert_raises(nx.NetworkXNoPath,nx.dijkstra_path_length,self.G,'s','moon') 86 87 assert_equal(nx.dijkstra_path(self.cycle,0,3),[0, 1, 2, 3]) 88 assert_equal(nx.dijkstra_path(self.cycle,0,4), [0, 6, 5, 4]) 89 90 assert_equal(nx.single_source_dijkstra(self.cycle,0,0),({0:0}, {0:[0]}) ) 91 92 def test_bidirectional_dijkstra(self): 93 assert_equal(nx.bidirectional_dijkstra(self.XG, 's', 'v'), 94 (9, ['s', 'x', 'u', 'v'])) 95 (dist,path) = nx.bidirectional_dijkstra(self.G,'s','v') 96 assert_equal(dist,2) 97 # skip this test, correct path could also be ['s','u','v'] 98 # assert_equal(nx.bidirectional_dijkstra(self.G,'s','v'), 99 # (2, ['s', 'x', 'v'])) 100 assert_equal(nx.bidirectional_dijkstra(self.cycle,0,3), 101 (3, [0, 1, 2, 3])) 102 assert_equal(nx.bidirectional_dijkstra(self.cycle,0,4), 103 (3, [0, 6, 5, 4])) 104 assert_equal(nx.bidirectional_dijkstra(self.XG3,0,3), 105 (15, [0, 1, 2, 3])) 106 assert_equal(nx.bidirectional_dijkstra(self.XG4,0,2), 107 (4, [0, 1, 2])) 108 109 # need more tests here 110 assert_equal(nx.dijkstra_path(self.XG,'s','v'), 111 nx.single_source_dijkstra_path(self.XG,'s')['v']) 112 113 114 @raises(nx.NetworkXNoPath) 115 def test_bidirectional_dijkstra_no_path(self): 116 G = nx.Graph() 117 G.add_path([1,2,3]) 118 G.add_path([4,5,6]) 119 path = nx.bidirectional_dijkstra(G,1,6) 120 121 def test_dijkstra_predecessor(self): 122 G=nx.path_graph(4) 123 assert_equal(nx.dijkstra_predecessor_and_distance(G,0), 124 ({0: [], 1: [0], 2: [1], 3: [2]}, {0: 0, 1: 1, 2: 2, 3: 3})) 125 G=nx.grid_2d_graph(2,2) 126 pred,dist=nx.dijkstra_predecessor_and_distance(G,(0,0)) 127 assert_equal(sorted(pred.items()), 128 [((0, 0), []), ((0, 1), [(0, 0)]), 129 ((1, 0), [(0, 0)]), ((1, 1), [(0, 1), (1, 0)])]) 130 assert_equal(sorted(dist.items()), 131 [((0, 0), 0), ((0, 1), 1), ((1, 0), 1), ((1, 1), 2)]) 132 133 XG=nx.DiGraph() 134 XG.add_weighted_edges_from([('s','u',10) ,('s','x',5) , 135 ('u','v',1) ,('u','x',2) , 136 ('v','y',1) ,('x','u',3) , 137 ('x','v',5) ,('x','y',2) , 138 ('y','s',7) ,('y','v',6)]) 139 (P,D)= nx.dijkstra_predecessor_and_distance(XG,'s') 140 assert_equal(P['v'],['u']) 141 assert_equal(D['v'],9) 142 (P,D)= nx.dijkstra_predecessor_and_distance(XG,'s',cutoff=8) 143 assert_false('v' in D) 144 145 def test_single_source_dijkstra_path_length(self): 146 pl = nx.single_source_dijkstra_path_length 147 assert_equal(pl(self.MXG4,0)[2], 4) 148 spl = pl(self.MXG4,0,cutoff=2) 149 assert_false(2 in spl) 150 151 def test_bidirectional_dijkstra_multigraph(self): 152 G = nx.MultiGraph() 153 G.add_edge('a', 'b', weight=10) 154 G.add_edge('a', 'b', weight=100) 155 dp= nx.bidirectional_dijkstra(G, 'a', 'b') 156 assert_equal(dp,(10, ['a', 'b'])) 157 158 159 def test_dijkstra_pred_distance_multigraph(self): 160 G = nx.MultiGraph() 161 G.add_edge('a', 'b', key='short',foo=5, weight=100) 162 G.add_edge('a', 'b', key='long',bar=1, weight=110) 163 p,d= nx.dijkstra_predecessor_and_distance(G, 'a') 164 assert_equal(p,{'a': [], 'b': ['a']}) 165 assert_equal(d,{'a': 0, 'b': 100}) 166 167 def test_negative_edge_cycle(self): 168 G = nx.cycle_graph(5, create_using = nx.DiGraph()) 169 assert_equal(nx.negative_edge_cycle(G), False) 170 G.add_edge(8, 9, weight = -7) 171 G.add_edge(9, 8, weight = 3) 172 assert_equal(nx.negative_edge_cycle(G), True) 173 assert_raises(ValueError,nx.single_source_dijkstra_path_length,G,8) 174 assert_raises(ValueError,nx.single_source_dijkstra,G,8) 175 assert_raises(ValueError,nx.dijkstra_predecessor_and_distance,G,8) 176 G.add_edge(9,10) 177 assert_raises(ValueError,nx.bidirectional_dijkstra,G,8,10) 178 179 def test_bellman_ford(self): 180 # single node graph 181 G = nx.DiGraph() 182 G.add_node(0) 183 assert_equal(nx.bellman_ford(G, 0), ({0: None}, {0: 0})) 184 assert_raises(KeyError, nx.bellman_ford, G, 1) 185 186 # negative weight cycle 187 G = nx.cycle_graph(5, create_using = nx.DiGraph()) 188 G.add_edge(1, 2, weight = -7) 189 for i in range(5): 190 assert_raises(nx.NetworkXUnbounded, nx.bellman_ford, G, i) 191 G = nx.cycle_graph(5) # undirected Graph 192 G.add_edge(1, 2, weight = -3) 193 for i in range(5): 194 assert_raises(nx.NetworkXUnbounded, nx.bellman_ford, G, i) 195 # no negative cycle but negative weight 196 G = nx.cycle_graph(5, create_using = nx.DiGraph()) 197 G.add_edge(1, 2, weight = -3) 198 assert_equal(nx.bellman_ford(G, 0), 199 ({0: None, 1: 0, 2: 1, 3: 2, 4: 3}, 200 {0: 0, 1: 1, 2: -2, 3: -1, 4: 0})) 201 202 # not connected 203 G = nx.complete_graph(6) 204 G.add_edge(10, 11) 205 G.add_edge(10, 12) 206 assert_equal(nx.bellman_ford(G, 0), 207 ({0: None, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0}, 208 {0: 0, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1})) 209 210 # not connected, with a component not containing the source that 211 # contains a negative cost cycle. 212 G = nx.complete_graph(6) 213 G.add_edges_from([('A', 'B', {'load': 3}), 214 ('B', 'C', {'load': -10}), 215 ('C', 'A', {'load': 2})]) 216 assert_equal(nx.bellman_ford(G, 0, weight = 'load'), 217 ({0: None, 1: 0, 2: 0, 3: 0, 4: 0, 5: 0}, 218 {0: 0, 1: 1, 2: 1, 3: 1, 4: 1, 5: 1})) 219 220 # multigraph 221 P, D = nx.bellman_ford(self.MXG,'s') 222 assert_equal(P['v'], 'u') 223 assert_equal(D['v'], 9) 224 P, D = nx.bellman_ford(self.MXG4, 0) 225 assert_equal(P[2], 1) 226 assert_equal(D[2], 4) 227 228 # other tests 229 (P,D)= nx.bellman_ford(self.XG,'s') 230 assert_equal(P['v'], 'u') 231 assert_equal(D['v'], 9) 232 233 G=nx.path_graph(4) 234 assert_equal(nx.bellman_ford(G,0), 235 ({0: None, 1: 0, 2: 1, 3: 2}, {0: 0, 1: 1, 2: 2, 3: 3})) 236 assert_equal(nx.bellman_ford(G, 3), 237 ({0: 1, 1: 2, 2: 3, 3: None}, {0: 3, 1: 2, 2: 1, 3: 0})) 238 239 G=nx.grid_2d_graph(2,2) 240 pred,dist=nx.bellman_ford(G,(0,0)) 241 assert_equal(sorted(pred.items()), 242 [((0, 0), None), ((0, 1), (0, 0)), 243 ((1, 0), (0, 0)), ((1, 1), (0, 1))]) 244 assert_equal(sorted(dist.items()), 245 [((0, 0), 0), ((0, 1), 1), ((1, 0), 1), ((1, 1), 2)]) 246 247