weighted.py 79 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488
  1. """
  2. Shortest path algorithms for weighted graphs.
  3. """
  4. from collections import deque
  5. from heapq import heappop, heappush
  6. from itertools import count
  7. import networkx as nx
  8. from networkx.algorithms.shortest_paths.generic import _build_paths_from_predecessors
  9. __all__ = [
  10. "dijkstra_path",
  11. "dijkstra_path_length",
  12. "bidirectional_dijkstra",
  13. "single_source_dijkstra",
  14. "single_source_dijkstra_path",
  15. "single_source_dijkstra_path_length",
  16. "multi_source_dijkstra",
  17. "multi_source_dijkstra_path",
  18. "multi_source_dijkstra_path_length",
  19. "all_pairs_dijkstra",
  20. "all_pairs_dijkstra_path",
  21. "all_pairs_dijkstra_path_length",
  22. "dijkstra_predecessor_and_distance",
  23. "bellman_ford_path",
  24. "bellman_ford_path_length",
  25. "single_source_bellman_ford",
  26. "single_source_bellman_ford_path",
  27. "single_source_bellman_ford_path_length",
  28. "all_pairs_bellman_ford_path",
  29. "all_pairs_bellman_ford_path_length",
  30. "bellman_ford_predecessor_and_distance",
  31. "negative_edge_cycle",
  32. "find_negative_cycle",
  33. "goldberg_radzik",
  34. "johnson",
  35. ]
  36. def _weight_function(G, weight):
  37. """Returns a function that returns the weight of an edge.
  38. The returned function is specifically suitable for input to
  39. functions :func:`_dijkstra` and :func:`_bellman_ford_relaxation`.
  40. Parameters
  41. ----------
  42. G : NetworkX graph.
  43. weight : string or function
  44. If it is callable, `weight` itself is returned. If it is a string,
  45. it is assumed to be the name of the edge attribute that represents
  46. the weight of an edge. In that case, a function is returned that
  47. gets the edge weight according to the specified edge attribute.
  48. Returns
  49. -------
  50. function
  51. This function returns a callable that accepts exactly three inputs:
  52. a node, an node adjacent to the first one, and the edge attribute
  53. dictionary for the eedge joining those nodes. That function returns
  54. a number representing the weight of an edge.
  55. If `G` is a multigraph, and `weight` is not callable, the
  56. minimum edge weight over all parallel edges is returned. If any edge
  57. does not have an attribute with key `weight`, it is assumed to
  58. have weight one.
  59. """
  60. if callable(weight):
  61. return weight
  62. # If the weight keyword argument is not callable, we assume it is a
  63. # string representing the edge attribute containing the weight of
  64. # the edge.
  65. if G.is_multigraph():
  66. return lambda u, v, d: min(attr.get(weight, 1) for attr in d.values())
  67. return lambda u, v, data: data.get(weight, 1)
  68. def dijkstra_path(G, source, target, weight="weight"):
  69. """Returns the shortest weighted path from source to target in G.
  70. Uses Dijkstra's Method to compute the shortest weighted path
  71. between two nodes in a graph.
  72. Parameters
  73. ----------
  74. G : NetworkX graph
  75. source : node
  76. Starting node
  77. target : node
  78. Ending node
  79. weight : string or function
  80. If this is a string, then edge weights will be accessed via the
  81. edge attribute with this key (that is, the weight of the edge
  82. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  83. such edge attribute exists, the weight of the edge is assumed to
  84. be one.
  85. If this is a function, the weight of an edge is the value
  86. returned by the function. The function must accept exactly three
  87. positional arguments: the two endpoints of an edge and the
  88. dictionary of edge attributes for that edge. The function must
  89. return a number or None to indicate a hidden edge.
  90. Returns
  91. -------
  92. path : list
  93. List of nodes in a shortest path.
  94. Raises
  95. ------
  96. NodeNotFound
  97. If `source` is not in `G`.
  98. NetworkXNoPath
  99. If no path exists between source and target.
  100. Examples
  101. --------
  102. >>> G = nx.path_graph(5)
  103. >>> print(nx.dijkstra_path(G, 0, 4))
  104. [0, 1, 2, 3, 4]
  105. Find edges of shortest path in Multigraph
  106. >>> G = nx.MultiDiGraph()
  107. >>> G.add_weighted_edges_from([(1, 2, 0.75), (1, 2, 0.5), (2, 3, 0.5), (1, 3, 1.5)])
  108. >>> nodes = nx.dijkstra_path(G, 1, 3)
  109. >>> edges = nx.utils.pairwise(nodes)
  110. >>> list((u, v, min(G[u][v], key=lambda k: G[u][v][k].get('weight', 1))) for u, v in edges)
  111. [(1, 2, 1), (2, 3, 0)]
  112. Notes
  113. -----
  114. Edge weight attributes must be numerical.
  115. Distances are calculated as sums of weighted edges traversed.
  116. The weight function can be used to hide edges by returning None.
  117. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  118. will find the shortest red path.
  119. The weight function can be used to include node weights.
  120. >>> def func(u, v, d):
  121. ... node_u_wt = G.nodes[u].get("node_weight", 1)
  122. ... node_v_wt = G.nodes[v].get("node_weight", 1)
  123. ... edge_wt = d.get("weight", 1)
  124. ... return node_u_wt / 2 + node_v_wt / 2 + edge_wt
  125. In this example we take the average of start and end node
  126. weights of an edge and add it to the weight of the edge.
  127. The function :func:`single_source_dijkstra` computes both
  128. path and length-of-path if you need both, use that.
  129. See Also
  130. --------
  131. bidirectional_dijkstra
  132. bellman_ford_path
  133. single_source_dijkstra
  134. """
  135. (length, path) = single_source_dijkstra(G, source, target=target, weight=weight)
  136. return path
  137. def dijkstra_path_length(G, source, target, weight="weight"):
  138. """Returns the shortest weighted path length in G from source to target.
  139. Uses Dijkstra's Method to compute the shortest weighted path length
  140. between two nodes in a graph.
  141. Parameters
  142. ----------
  143. G : NetworkX graph
  144. source : node label
  145. starting node for path
  146. target : node label
  147. ending node for path
  148. weight : string or function
  149. If this is a string, then edge weights will be accessed via the
  150. edge attribute with this key (that is, the weight of the edge
  151. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  152. such edge attribute exists, the weight of the edge is assumed to
  153. be one.
  154. If this is a function, the weight of an edge is the value
  155. returned by the function. The function must accept exactly three
  156. positional arguments: the two endpoints of an edge and the
  157. dictionary of edge attributes for that edge. The function must
  158. return a number or None to indicate a hidden edge.
  159. Returns
  160. -------
  161. length : number
  162. Shortest path length.
  163. Raises
  164. ------
  165. NodeNotFound
  166. If `source` is not in `G`.
  167. NetworkXNoPath
  168. If no path exists between source and target.
  169. Examples
  170. --------
  171. >>> G = nx.path_graph(5)
  172. >>> nx.dijkstra_path_length(G, 0, 4)
  173. 4
  174. Notes
  175. -----
  176. Edge weight attributes must be numerical.
  177. Distances are calculated as sums of weighted edges traversed.
  178. The weight function can be used to hide edges by returning None.
  179. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  180. will find the shortest red path.
  181. The function :func:`single_source_dijkstra` computes both
  182. path and length-of-path if you need both, use that.
  183. See Also
  184. --------
  185. bidirectional_dijkstra
  186. bellman_ford_path_length
  187. single_source_dijkstra
  188. """
  189. if source not in G:
  190. raise nx.NodeNotFound(f"Node {source} not found in graph")
  191. if source == target:
  192. return 0
  193. weight = _weight_function(G, weight)
  194. length = _dijkstra(G, source, weight, target=target)
  195. try:
  196. return length[target]
  197. except KeyError as err:
  198. raise nx.NetworkXNoPath(f"Node {target} not reachable from {source}") from err
  199. def single_source_dijkstra_path(G, source, cutoff=None, weight="weight"):
  200. """Find shortest weighted paths in G from a source node.
  201. Compute shortest path between source and all other reachable
  202. nodes for a weighted graph.
  203. Parameters
  204. ----------
  205. G : NetworkX graph
  206. source : node
  207. Starting node for path.
  208. cutoff : integer or float, optional
  209. Length (sum of edge weights) at which the search is stopped.
  210. If cutoff is provided, only return paths with summed weight <= cutoff.
  211. weight : string or function
  212. If this is a string, then edge weights will be accessed via the
  213. edge attribute with this key (that is, the weight of the edge
  214. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  215. such edge attribute exists, the weight of the edge is assumed to
  216. be one.
  217. If this is a function, the weight of an edge is the value
  218. returned by the function. The function must accept exactly three
  219. positional arguments: the two endpoints of an edge and the
  220. dictionary of edge attributes for that edge. The function must
  221. return a number or None to indicate a hidden edge.
  222. Returns
  223. -------
  224. paths : dictionary
  225. Dictionary of shortest path lengths keyed by target.
  226. Raises
  227. ------
  228. NodeNotFound
  229. If `source` is not in `G`.
  230. Examples
  231. --------
  232. >>> G = nx.path_graph(5)
  233. >>> path = nx.single_source_dijkstra_path(G, 0)
  234. >>> path[4]
  235. [0, 1, 2, 3, 4]
  236. Notes
  237. -----
  238. Edge weight attributes must be numerical.
  239. Distances are calculated as sums of weighted edges traversed.
  240. The weight function can be used to hide edges by returning None.
  241. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  242. will find the shortest red path.
  243. See Also
  244. --------
  245. single_source_dijkstra, single_source_bellman_ford
  246. """
  247. return multi_source_dijkstra_path(G, {source}, cutoff=cutoff, weight=weight)
  248. def single_source_dijkstra_path_length(G, source, cutoff=None, weight="weight"):
  249. """Find shortest weighted path lengths in G from a source node.
  250. Compute the shortest path length between source and all other
  251. reachable nodes for a weighted graph.
  252. Parameters
  253. ----------
  254. G : NetworkX graph
  255. source : node label
  256. Starting node for path
  257. cutoff : integer or float, optional
  258. Length (sum of edge weights) at which the search is stopped.
  259. If cutoff is provided, only return paths with summed weight <= cutoff.
  260. weight : string or function
  261. If this is a string, then edge weights will be accessed via the
  262. edge attribute with this key (that is, the weight of the edge
  263. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  264. such edge attribute exists, the weight of the edge is assumed to
  265. be one.
  266. If this is a function, the weight of an edge is the value
  267. returned by the function. The function must accept exactly three
  268. positional arguments: the two endpoints of an edge and the
  269. dictionary of edge attributes for that edge. The function must
  270. return a number or None to indicate a hidden edge.
  271. Returns
  272. -------
  273. length : dict
  274. Dict keyed by node to shortest path length from source.
  275. Raises
  276. ------
  277. NodeNotFound
  278. If `source` is not in `G`.
  279. Examples
  280. --------
  281. >>> G = nx.path_graph(5)
  282. >>> length = nx.single_source_dijkstra_path_length(G, 0)
  283. >>> length[4]
  284. 4
  285. >>> for node in [0, 1, 2, 3, 4]:
  286. ... print(f"{node}: {length[node]}")
  287. 0: 0
  288. 1: 1
  289. 2: 2
  290. 3: 3
  291. 4: 4
  292. Notes
  293. -----
  294. Edge weight attributes must be numerical.
  295. Distances are calculated as sums of weighted edges traversed.
  296. The weight function can be used to hide edges by returning None.
  297. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  298. will find the shortest red path.
  299. See Also
  300. --------
  301. single_source_dijkstra, single_source_bellman_ford_path_length
  302. """
  303. return multi_source_dijkstra_path_length(G, {source}, cutoff=cutoff, weight=weight)
  304. def single_source_dijkstra(G, source, target=None, cutoff=None, weight="weight"):
  305. """Find shortest weighted paths and lengths from a source node.
  306. Compute the shortest path length between source and all other
  307. reachable nodes for a weighted graph.
  308. Uses Dijkstra's algorithm to compute shortest paths and lengths
  309. between a source and all other reachable nodes in a weighted graph.
  310. Parameters
  311. ----------
  312. G : NetworkX graph
  313. source : node label
  314. Starting node for path
  315. target : node label, optional
  316. Ending node for path
  317. cutoff : integer or float, optional
  318. Length (sum of edge weights) at which the search is stopped.
  319. If cutoff is provided, only return paths with summed weight <= cutoff.
  320. weight : string or function
  321. If this is a string, then edge weights will be accessed via the
  322. edge attribute with this key (that is, the weight of the edge
  323. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  324. such edge attribute exists, the weight of the edge is assumed to
  325. be one.
  326. If this is a function, the weight of an edge is the value
  327. returned by the function. The function must accept exactly three
  328. positional arguments: the two endpoints of an edge and the
  329. dictionary of edge attributes for that edge. The function must
  330. return a number or None to indicate a hidden edge.
  331. Returns
  332. -------
  333. distance, path : pair of dictionaries, or numeric and list.
  334. If target is None, paths and lengths to all nodes are computed.
  335. The return value is a tuple of two dictionaries keyed by target nodes.
  336. The first dictionary stores distance to each target node.
  337. The second stores the path to each target node.
  338. If target is not None, returns a tuple (distance, path), where
  339. distance is the distance from source to target and path is a list
  340. representing the path from source to target.
  341. Raises
  342. ------
  343. NodeNotFound
  344. If `source` is not in `G`.
  345. Examples
  346. --------
  347. >>> G = nx.path_graph(5)
  348. >>> length, path = nx.single_source_dijkstra(G, 0)
  349. >>> length[4]
  350. 4
  351. >>> for node in [0, 1, 2, 3, 4]:
  352. ... print(f"{node}: {length[node]}")
  353. 0: 0
  354. 1: 1
  355. 2: 2
  356. 3: 3
  357. 4: 4
  358. >>> path[4]
  359. [0, 1, 2, 3, 4]
  360. >>> length, path = nx.single_source_dijkstra(G, 0, 1)
  361. >>> length
  362. 1
  363. >>> path
  364. [0, 1]
  365. Notes
  366. -----
  367. Edge weight attributes must be numerical.
  368. Distances are calculated as sums of weighted edges traversed.
  369. The weight function can be used to hide edges by returning None.
  370. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  371. will find the shortest red path.
  372. Based on the Python cookbook recipe (119466) at
  373. https://code.activestate.com/recipes/119466/
  374. This algorithm is not guaranteed to work if edge weights
  375. are negative or are floating point numbers
  376. (overflows and roundoff errors can cause problems).
  377. See Also
  378. --------
  379. single_source_dijkstra_path
  380. single_source_dijkstra_path_length
  381. single_source_bellman_ford
  382. """
  383. return multi_source_dijkstra(
  384. G, {source}, cutoff=cutoff, target=target, weight=weight
  385. )
  386. def multi_source_dijkstra_path(G, sources, cutoff=None, weight="weight"):
  387. """Find shortest weighted paths in G from a given set of source
  388. nodes.
  389. Compute shortest path between any of the source nodes and all other
  390. reachable nodes for a weighted graph.
  391. Parameters
  392. ----------
  393. G : NetworkX graph
  394. sources : non-empty set of nodes
  395. Starting nodes for paths. If this is just a set containing a
  396. single node, then all paths computed by this function will start
  397. from that node. If there are two or more nodes in the set, the
  398. computed paths may begin from any one of the start nodes.
  399. cutoff : integer or float, optional
  400. Length (sum of edge weights) at which the search is stopped.
  401. If cutoff is provided, only return paths with summed weight <= cutoff.
  402. weight : string or function
  403. If this is a string, then edge weights will be accessed via the
  404. edge attribute with this key (that is, the weight of the edge
  405. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  406. such edge attribute exists, the weight of the edge is assumed to
  407. be one.
  408. If this is a function, the weight of an edge is the value
  409. returned by the function. The function must accept exactly three
  410. positional arguments: the two endpoints of an edge and the
  411. dictionary of edge attributes for that edge. The function must
  412. return a number or None to indicate a hidden edge.
  413. Returns
  414. -------
  415. paths : dictionary
  416. Dictionary of shortest paths keyed by target.
  417. Examples
  418. --------
  419. >>> G = nx.path_graph(5)
  420. >>> path = nx.multi_source_dijkstra_path(G, {0, 4})
  421. >>> path[1]
  422. [0, 1]
  423. >>> path[3]
  424. [4, 3]
  425. Notes
  426. -----
  427. Edge weight attributes must be numerical.
  428. Distances are calculated as sums of weighted edges traversed.
  429. The weight function can be used to hide edges by returning None.
  430. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  431. will find the shortest red path.
  432. Raises
  433. ------
  434. ValueError
  435. If `sources` is empty.
  436. NodeNotFound
  437. If any of `sources` is not in `G`.
  438. See Also
  439. --------
  440. multi_source_dijkstra, multi_source_bellman_ford
  441. """
  442. length, path = multi_source_dijkstra(G, sources, cutoff=cutoff, weight=weight)
  443. return path
  444. def multi_source_dijkstra_path_length(G, sources, cutoff=None, weight="weight"):
  445. """Find shortest weighted path lengths in G from a given set of
  446. source nodes.
  447. Compute the shortest path length between any of the source nodes and
  448. all other reachable nodes for a weighted graph.
  449. Parameters
  450. ----------
  451. G : NetworkX graph
  452. sources : non-empty set of nodes
  453. Starting nodes for paths. If this is just a set containing a
  454. single node, then all paths computed by this function will start
  455. from that node. If there are two or more nodes in the set, the
  456. computed paths may begin from any one of the start nodes.
  457. cutoff : integer or float, optional
  458. Length (sum of edge weights) at which the search is stopped.
  459. If cutoff is provided, only return paths with summed weight <= cutoff.
  460. weight : string or function
  461. If this is a string, then edge weights will be accessed via the
  462. edge attribute with this key (that is, the weight of the edge
  463. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  464. such edge attribute exists, the weight of the edge is assumed to
  465. be one.
  466. If this is a function, the weight of an edge is the value
  467. returned by the function. The function must accept exactly three
  468. positional arguments: the two endpoints of an edge and the
  469. dictionary of edge attributes for that edge. The function must
  470. return a number or None to indicate a hidden edge.
  471. Returns
  472. -------
  473. length : dict
  474. Dict keyed by node to shortest path length to nearest source.
  475. Examples
  476. --------
  477. >>> G = nx.path_graph(5)
  478. >>> length = nx.multi_source_dijkstra_path_length(G, {0, 4})
  479. >>> for node in [0, 1, 2, 3, 4]:
  480. ... print(f"{node}: {length[node]}")
  481. 0: 0
  482. 1: 1
  483. 2: 2
  484. 3: 1
  485. 4: 0
  486. Notes
  487. -----
  488. Edge weight attributes must be numerical.
  489. Distances are calculated as sums of weighted edges traversed.
  490. The weight function can be used to hide edges by returning None.
  491. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  492. will find the shortest red path.
  493. Raises
  494. ------
  495. ValueError
  496. If `sources` is empty.
  497. NodeNotFound
  498. If any of `sources` is not in `G`.
  499. See Also
  500. --------
  501. multi_source_dijkstra
  502. """
  503. if not sources:
  504. raise ValueError("sources must not be empty")
  505. for s in sources:
  506. if s not in G:
  507. raise nx.NodeNotFound(f"Node {s} not found in graph")
  508. weight = _weight_function(G, weight)
  509. return _dijkstra_multisource(G, sources, weight, cutoff=cutoff)
  510. def multi_source_dijkstra(G, sources, target=None, cutoff=None, weight="weight"):
  511. """Find shortest weighted paths and lengths from a given set of
  512. source nodes.
  513. Uses Dijkstra's algorithm to compute the shortest paths and lengths
  514. between one of the source nodes and the given `target`, or all other
  515. reachable nodes if not specified, for a weighted graph.
  516. Parameters
  517. ----------
  518. G : NetworkX graph
  519. sources : non-empty set of nodes
  520. Starting nodes for paths. If this is just a set containing a
  521. single node, then all paths computed by this function will start
  522. from that node. If there are two or more nodes in the set, the
  523. computed paths may begin from any one of the start nodes.
  524. target : node label, optional
  525. Ending node for path
  526. cutoff : integer or float, optional
  527. Length (sum of edge weights) at which the search is stopped.
  528. If cutoff is provided, only return paths with summed weight <= cutoff.
  529. weight : string or function
  530. If this is a string, then edge weights will be accessed via the
  531. edge attribute with this key (that is, the weight of the edge
  532. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  533. such edge attribute exists, the weight of the edge is assumed to
  534. be one.
  535. If this is a function, the weight of an edge is the value
  536. returned by the function. The function must accept exactly three
  537. positional arguments: the two endpoints of an edge and the
  538. dictionary of edge attributes for that edge. The function must
  539. return a number or None to indicate a hidden edge.
  540. Returns
  541. -------
  542. distance, path : pair of dictionaries, or numeric and list
  543. If target is None, returns a tuple of two dictionaries keyed by node.
  544. The first dictionary stores distance from one of the source nodes.
  545. The second stores the path from one of the sources to that node.
  546. If target is not None, returns a tuple of (distance, path) where
  547. distance is the distance from source to target and path is a list
  548. representing the path from source to target.
  549. Examples
  550. --------
  551. >>> G = nx.path_graph(5)
  552. >>> length, path = nx.multi_source_dijkstra(G, {0, 4})
  553. >>> for node in [0, 1, 2, 3, 4]:
  554. ... print(f"{node}: {length[node]}")
  555. 0: 0
  556. 1: 1
  557. 2: 2
  558. 3: 1
  559. 4: 0
  560. >>> path[1]
  561. [0, 1]
  562. >>> path[3]
  563. [4, 3]
  564. >>> length, path = nx.multi_source_dijkstra(G, {0, 4}, 1)
  565. >>> length
  566. 1
  567. >>> path
  568. [0, 1]
  569. Notes
  570. -----
  571. Edge weight attributes must be numerical.
  572. Distances are calculated as sums of weighted edges traversed.
  573. The weight function can be used to hide edges by returning None.
  574. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  575. will find the shortest red path.
  576. Based on the Python cookbook recipe (119466) at
  577. https://code.activestate.com/recipes/119466/
  578. This algorithm is not guaranteed to work if edge weights
  579. are negative or are floating point numbers
  580. (overflows and roundoff errors can cause problems).
  581. Raises
  582. ------
  583. ValueError
  584. If `sources` is empty.
  585. NodeNotFound
  586. If any of `sources` is not in `G`.
  587. See Also
  588. --------
  589. multi_source_dijkstra_path
  590. multi_source_dijkstra_path_length
  591. """
  592. if not sources:
  593. raise ValueError("sources must not be empty")
  594. for s in sources:
  595. if s not in G:
  596. raise nx.NodeNotFound(f"Node {s} not found in graph")
  597. if target in sources:
  598. return (0, [target])
  599. weight = _weight_function(G, weight)
  600. paths = {source: [source] for source in sources} # dictionary of paths
  601. dist = _dijkstra_multisource(
  602. G, sources, weight, paths=paths, cutoff=cutoff, target=target
  603. )
  604. if target is None:
  605. return (dist, paths)
  606. try:
  607. return (dist[target], paths[target])
  608. except KeyError as err:
  609. raise nx.NetworkXNoPath(f"No path to {target}.") from err
  610. def _dijkstra(G, source, weight, pred=None, paths=None, cutoff=None, target=None):
  611. """Uses Dijkstra's algorithm to find shortest weighted paths from a
  612. single source.
  613. This is a convenience function for :func:`_dijkstra_multisource`
  614. with all the arguments the same, except the keyword argument
  615. `sources` set to ``[source]``.
  616. """
  617. return _dijkstra_multisource(
  618. G, [source], weight, pred=pred, paths=paths, cutoff=cutoff, target=target
  619. )
  620. def _dijkstra_multisource(
  621. G, sources, weight, pred=None, paths=None, cutoff=None, target=None
  622. ):
  623. """Uses Dijkstra's algorithm to find shortest weighted paths
  624. Parameters
  625. ----------
  626. G : NetworkX graph
  627. sources : non-empty iterable of nodes
  628. Starting nodes for paths. If this is just an iterable containing
  629. a single node, then all paths computed by this function will
  630. start from that node. If there are two or more nodes in this
  631. iterable, the computed paths may begin from any one of the start
  632. nodes.
  633. weight: function
  634. Function with (u, v, data) input that returns that edge's weight
  635. or None to indicate a hidden edge
  636. pred: dict of lists, optional(default=None)
  637. dict to store a list of predecessors keyed by that node
  638. If None, predecessors are not stored.
  639. paths: dict, optional (default=None)
  640. dict to store the path list from source to each node, keyed by node.
  641. If None, paths are not stored.
  642. target : node label, optional
  643. Ending node for path. Search is halted when target is found.
  644. cutoff : integer or float, optional
  645. Length (sum of edge weights) at which the search is stopped.
  646. If cutoff is provided, only return paths with summed weight <= cutoff.
  647. Returns
  648. -------
  649. distance : dictionary
  650. A mapping from node to shortest distance to that node from one
  651. of the source nodes.
  652. Raises
  653. ------
  654. NodeNotFound
  655. If any of `sources` is not in `G`.
  656. Notes
  657. -----
  658. The optional predecessor and path dictionaries can be accessed by
  659. the caller through the original pred and paths objects passed
  660. as arguments. No need to explicitly return pred or paths.
  661. """
  662. G_succ = G._adj # For speed-up (and works for both directed and undirected graphs)
  663. push = heappush
  664. pop = heappop
  665. dist = {} # dictionary of final distances
  666. seen = {}
  667. # fringe is heapq with 3-tuples (distance,c,node)
  668. # use the count c to avoid comparing nodes (may not be able to)
  669. c = count()
  670. fringe = []
  671. for source in sources:
  672. seen[source] = 0
  673. push(fringe, (0, next(c), source))
  674. while fringe:
  675. (d, _, v) = pop(fringe)
  676. if v in dist:
  677. continue # already searched this node.
  678. dist[v] = d
  679. if v == target:
  680. break
  681. for u, e in G_succ[v].items():
  682. cost = weight(v, u, e)
  683. if cost is None:
  684. continue
  685. vu_dist = dist[v] + cost
  686. if cutoff is not None:
  687. if vu_dist > cutoff:
  688. continue
  689. if u in dist:
  690. u_dist = dist[u]
  691. if vu_dist < u_dist:
  692. raise ValueError("Contradictory paths found:", "negative weights?")
  693. elif pred is not None and vu_dist == u_dist:
  694. pred[u].append(v)
  695. elif u not in seen or vu_dist < seen[u]:
  696. seen[u] = vu_dist
  697. push(fringe, (vu_dist, next(c), u))
  698. if paths is not None:
  699. paths[u] = paths[v] + [u]
  700. if pred is not None:
  701. pred[u] = [v]
  702. elif vu_dist == seen[u]:
  703. if pred is not None:
  704. pred[u].append(v)
  705. # The optional predecessor and path dictionaries can be accessed
  706. # by the caller via the pred and paths objects passed as arguments.
  707. return dist
  708. def dijkstra_predecessor_and_distance(G, source, cutoff=None, weight="weight"):
  709. """Compute weighted shortest path length and predecessors.
  710. Uses Dijkstra's Method to obtain the shortest weighted paths
  711. and return dictionaries of predecessors for each node and
  712. distance for each node from the `source`.
  713. Parameters
  714. ----------
  715. G : NetworkX graph
  716. source : node label
  717. Starting node for path
  718. cutoff : integer or float, optional
  719. Length (sum of edge weights) at which the search is stopped.
  720. If cutoff is provided, only return paths with summed weight <= cutoff.
  721. weight : string or function
  722. If this is a string, then edge weights will be accessed via the
  723. edge attribute with this key (that is, the weight of the edge
  724. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  725. such edge attribute exists, the weight of the edge is assumed to
  726. be one.
  727. If this is a function, the weight of an edge is the value
  728. returned by the function. The function must accept exactly three
  729. positional arguments: the two endpoints of an edge and the
  730. dictionary of edge attributes for that edge. The function must
  731. return a number or None to indicate a hidden edge.
  732. Returns
  733. -------
  734. pred, distance : dictionaries
  735. Returns two dictionaries representing a list of predecessors
  736. of a node and the distance to each node.
  737. Raises
  738. ------
  739. NodeNotFound
  740. If `source` is not in `G`.
  741. Notes
  742. -----
  743. Edge weight attributes must be numerical.
  744. Distances are calculated as sums of weighted edges traversed.
  745. The list of predecessors contains more than one element only when
  746. there are more than one shortest paths to the key node.
  747. Examples
  748. --------
  749. >>> G = nx.path_graph(5, create_using=nx.DiGraph())
  750. >>> pred, dist = nx.dijkstra_predecessor_and_distance(G, 0)
  751. >>> sorted(pred.items())
  752. [(0, []), (1, [0]), (2, [1]), (3, [2]), (4, [3])]
  753. >>> sorted(dist.items())
  754. [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
  755. >>> pred, dist = nx.dijkstra_predecessor_and_distance(G, 0, 1)
  756. >>> sorted(pred.items())
  757. [(0, []), (1, [0])]
  758. >>> sorted(dist.items())
  759. [(0, 0), (1, 1)]
  760. """
  761. if source not in G:
  762. raise nx.NodeNotFound(f"Node {source} is not found in the graph")
  763. weight = _weight_function(G, weight)
  764. pred = {source: []} # dictionary of predecessors
  765. return (pred, _dijkstra(G, source, weight, pred=pred, cutoff=cutoff))
  766. def all_pairs_dijkstra(G, cutoff=None, weight="weight"):
  767. """Find shortest weighted paths and lengths between all nodes.
  768. Parameters
  769. ----------
  770. G : NetworkX graph
  771. cutoff : integer or float, optional
  772. Length (sum of edge weights) at which the search is stopped.
  773. If cutoff is provided, only return paths with summed weight <= cutoff.
  774. weight : string or function
  775. If this is a string, then edge weights will be accessed via the
  776. edge attribute with this key (that is, the weight of the edge
  777. joining `u` to `v` will be ``G.edge[u][v][weight]``). If no
  778. such edge attribute exists, the weight of the edge is assumed to
  779. be one.
  780. If this is a function, the weight of an edge is the value
  781. returned by the function. The function must accept exactly three
  782. positional arguments: the two endpoints of an edge and the
  783. dictionary of edge attributes for that edge. The function must
  784. return a number or None to indicate a hidden edge.
  785. Yields
  786. ------
  787. (node, (distance, path)) : (node obj, (dict, dict))
  788. Each source node has two associated dicts. The first holds distance
  789. keyed by target and the second holds paths keyed by target.
  790. (See single_source_dijkstra for the source/target node terminology.)
  791. If desired you can apply `dict()` to this function to create a dict
  792. keyed by source node to the two dicts.
  793. Examples
  794. --------
  795. >>> G = nx.path_graph(5)
  796. >>> len_path = dict(nx.all_pairs_dijkstra(G))
  797. >>> len_path[3][0][1]
  798. 2
  799. >>> for node in [0, 1, 2, 3, 4]:
  800. ... print(f"3 - {node}: {len_path[3][0][node]}")
  801. 3 - 0: 3
  802. 3 - 1: 2
  803. 3 - 2: 1
  804. 3 - 3: 0
  805. 3 - 4: 1
  806. >>> len_path[3][1][1]
  807. [3, 2, 1]
  808. >>> for n, (dist, path) in nx.all_pairs_dijkstra(G):
  809. ... print(path[1])
  810. [0, 1]
  811. [1]
  812. [2, 1]
  813. [3, 2, 1]
  814. [4, 3, 2, 1]
  815. Notes
  816. -----
  817. Edge weight attributes must be numerical.
  818. Distances are calculated as sums of weighted edges traversed.
  819. The yielded dicts only have keys for reachable nodes.
  820. """
  821. for n in G:
  822. dist, path = single_source_dijkstra(G, n, cutoff=cutoff, weight=weight)
  823. yield (n, (dist, path))
  824. def all_pairs_dijkstra_path_length(G, cutoff=None, weight="weight"):
  825. """Compute shortest path lengths between all nodes in a weighted graph.
  826. Parameters
  827. ----------
  828. G : NetworkX graph
  829. cutoff : integer or float, optional
  830. Length (sum of edge weights) at which the search is stopped.
  831. If cutoff is provided, only return paths with summed weight <= cutoff.
  832. weight : string or function
  833. If this is a string, then edge weights will be accessed via the
  834. edge attribute with this key (that is, the weight of the edge
  835. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  836. such edge attribute exists, the weight of the edge is assumed to
  837. be one.
  838. If this is a function, the weight of an edge is the value
  839. returned by the function. The function must accept exactly three
  840. positional arguments: the two endpoints of an edge and the
  841. dictionary of edge attributes for that edge. The function must
  842. return a number or None to indicate a hidden edge.
  843. Returns
  844. -------
  845. distance : iterator
  846. (source, dictionary) iterator with dictionary keyed by target and
  847. shortest path length as the key value.
  848. Examples
  849. --------
  850. >>> G = nx.path_graph(5)
  851. >>> length = dict(nx.all_pairs_dijkstra_path_length(G))
  852. >>> for node in [0, 1, 2, 3, 4]:
  853. ... print(f"1 - {node}: {length[1][node]}")
  854. 1 - 0: 1
  855. 1 - 1: 0
  856. 1 - 2: 1
  857. 1 - 3: 2
  858. 1 - 4: 3
  859. >>> length[3][2]
  860. 1
  861. >>> length[2][2]
  862. 0
  863. Notes
  864. -----
  865. Edge weight attributes must be numerical.
  866. Distances are calculated as sums of weighted edges traversed.
  867. The dictionary returned only has keys for reachable node pairs.
  868. """
  869. length = single_source_dijkstra_path_length
  870. for n in G:
  871. yield (n, length(G, n, cutoff=cutoff, weight=weight))
  872. def all_pairs_dijkstra_path(G, cutoff=None, weight="weight"):
  873. """Compute shortest paths between all nodes in a weighted graph.
  874. Parameters
  875. ----------
  876. G : NetworkX graph
  877. cutoff : integer or float, optional
  878. Length (sum of edge weights) at which the search is stopped.
  879. If cutoff is provided, only return paths with summed weight <= cutoff.
  880. weight : string or function
  881. If this is a string, then edge weights will be accessed via the
  882. edge attribute with this key (that is, the weight of the edge
  883. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  884. such edge attribute exists, the weight of the edge is assumed to
  885. be one.
  886. If this is a function, the weight of an edge is the value
  887. returned by the function. The function must accept exactly three
  888. positional arguments: the two endpoints of an edge and the
  889. dictionary of edge attributes for that edge. The function must
  890. return a number or None to indicate a hidden edge.
  891. Returns
  892. -------
  893. paths : iterator
  894. (source, dictionary) iterator with dictionary keyed by target and
  895. shortest path as the key value.
  896. Examples
  897. --------
  898. >>> G = nx.path_graph(5)
  899. >>> path = dict(nx.all_pairs_dijkstra_path(G))
  900. >>> path[0][4]
  901. [0, 1, 2, 3, 4]
  902. Notes
  903. -----
  904. Edge weight attributes must be numerical.
  905. Distances are calculated as sums of weighted edges traversed.
  906. See Also
  907. --------
  908. floyd_warshall, all_pairs_bellman_ford_path
  909. """
  910. path = single_source_dijkstra_path
  911. # TODO This can be trivially parallelized.
  912. for n in G:
  913. yield (n, path(G, n, cutoff=cutoff, weight=weight))
  914. @nx._dispatch
  915. def bellman_ford_predecessor_and_distance(
  916. G, source, target=None, weight="weight", heuristic=False
  917. ):
  918. """Compute shortest path lengths and predecessors on shortest paths
  919. in weighted graphs.
  920. The algorithm has a running time of $O(mn)$ where $n$ is the number of
  921. nodes and $m$ is the number of edges. It is slower than Dijkstra but
  922. can handle negative edge weights.
  923. If a negative cycle is detected, you can use :func:`find_negative_cycle`
  924. to return the cycle and examine it. Shortest paths are not defined when
  925. a negative cycle exists because once reached, the path can cycle forever
  926. to build up arbitrarily low weights.
  927. Parameters
  928. ----------
  929. G : NetworkX graph
  930. The algorithm works for all types of graphs, including directed
  931. graphs and multigraphs.
  932. source: node label
  933. Starting node for path
  934. target : node label, optional
  935. Ending node for path
  936. weight : string or function
  937. If this is a string, then edge weights will be accessed via the
  938. edge attribute with this key (that is, the weight of the edge
  939. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  940. such edge attribute exists, the weight of the edge is assumed to
  941. be one.
  942. If this is a function, the weight of an edge is the value
  943. returned by the function. The function must accept exactly three
  944. positional arguments: the two endpoints of an edge and the
  945. dictionary of edge attributes for that edge. The function must
  946. return a number.
  947. heuristic : bool
  948. Determines whether to use a heuristic to early detect negative
  949. cycles at a hopefully negligible cost.
  950. Returns
  951. -------
  952. pred, dist : dictionaries
  953. Returns two dictionaries keyed by node to predecessor in the
  954. path and to the distance from the source respectively.
  955. Raises
  956. ------
  957. NodeNotFound
  958. If `source` is not in `G`.
  959. NetworkXUnbounded
  960. If the (di)graph contains a negative (di)cycle, the
  961. algorithm raises an exception to indicate the presence of the
  962. negative (di)cycle. Note: any negative weight edge in an
  963. undirected graph is a negative cycle.
  964. Examples
  965. --------
  966. >>> G = nx.path_graph(5, create_using=nx.DiGraph())
  967. >>> pred, dist = nx.bellman_ford_predecessor_and_distance(G, 0)
  968. >>> sorted(pred.items())
  969. [(0, []), (1, [0]), (2, [1]), (3, [2]), (4, [3])]
  970. >>> sorted(dist.items())
  971. [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
  972. >>> pred, dist = nx.bellman_ford_predecessor_and_distance(G, 0, 1)
  973. >>> sorted(pred.items())
  974. [(0, []), (1, [0]), (2, [1]), (3, [2]), (4, [3])]
  975. >>> sorted(dist.items())
  976. [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
  977. >>> G = nx.cycle_graph(5, create_using=nx.DiGraph())
  978. >>> G[1][2]["weight"] = -7
  979. >>> nx.bellman_ford_predecessor_and_distance(G, 0)
  980. Traceback (most recent call last):
  981. ...
  982. networkx.exception.NetworkXUnbounded: Negative cycle detected.
  983. See Also
  984. --------
  985. find_negative_cycle
  986. Notes
  987. -----
  988. Edge weight attributes must be numerical.
  989. Distances are calculated as sums of weighted edges traversed.
  990. The dictionaries returned only have keys for nodes reachable from
  991. the source.
  992. In the case where the (di)graph is not connected, if a component
  993. not containing the source contains a negative (di)cycle, it
  994. will not be detected.
  995. In NetworkX v2.1 and prior, the source node had predecessor `[None]`.
  996. In NetworkX v2.2 this changed to the source node having predecessor `[]`
  997. """
  998. if source not in G:
  999. raise nx.NodeNotFound(f"Node {source} is not found in the graph")
  1000. weight = _weight_function(G, weight)
  1001. if any(weight(u, v, d) < 0 for u, v, d in nx.selfloop_edges(G, data=True)):
  1002. raise nx.NetworkXUnbounded("Negative cycle detected.")
  1003. dist = {source: 0}
  1004. pred = {source: []}
  1005. if len(G) == 1:
  1006. return pred, dist
  1007. weight = _weight_function(G, weight)
  1008. dist = _bellman_ford(
  1009. G, [source], weight, pred=pred, dist=dist, target=target, heuristic=heuristic
  1010. )
  1011. return (pred, dist)
  1012. def _bellman_ford(
  1013. G,
  1014. source,
  1015. weight,
  1016. pred=None,
  1017. paths=None,
  1018. dist=None,
  1019. target=None,
  1020. heuristic=True,
  1021. ):
  1022. """Calls relaxation loop for Bellman–Ford algorithm and builds paths
  1023. This is an implementation of the SPFA variant.
  1024. See https://en.wikipedia.org/wiki/Shortest_Path_Faster_Algorithm
  1025. Parameters
  1026. ----------
  1027. G : NetworkX graph
  1028. source: list
  1029. List of source nodes. The shortest path from any of the source
  1030. nodes will be found if multiple sources are provided.
  1031. weight : function
  1032. The weight of an edge is the value returned by the function. The
  1033. function must accept exactly three positional arguments: the two
  1034. endpoints of an edge and the dictionary of edge attributes for
  1035. that edge. The function must return a number.
  1036. pred: dict of lists, optional (default=None)
  1037. dict to store a list of predecessors keyed by that node
  1038. If None, predecessors are not stored
  1039. paths: dict, optional (default=None)
  1040. dict to store the path list from source to each node, keyed by node
  1041. If None, paths are not stored
  1042. dist: dict, optional (default=None)
  1043. dict to store distance from source to the keyed node
  1044. If None, returned dist dict contents default to 0 for every node in the
  1045. source list
  1046. target: node label, optional
  1047. Ending node for path. Path lengths to other destinations may (and
  1048. probably will) be incorrect.
  1049. heuristic : bool
  1050. Determines whether to use a heuristic to early detect negative
  1051. cycles at a hopefully negligible cost.
  1052. Returns
  1053. -------
  1054. dist : dict
  1055. Returns a dict keyed by node to the distance from the source.
  1056. Dicts for paths and pred are in the mutated input dicts by those names.
  1057. Raises
  1058. ------
  1059. NodeNotFound
  1060. If any of `source` is not in `G`.
  1061. NetworkXUnbounded
  1062. If the (di)graph contains a negative (di)cycle, the
  1063. algorithm raises an exception to indicate the presence of the
  1064. negative (di)cycle. Note: any negative weight edge in an
  1065. undirected graph is a negative cycle
  1066. """
  1067. if pred is None:
  1068. pred = {v: [] for v in source}
  1069. if dist is None:
  1070. dist = {v: 0 for v in source}
  1071. negative_cycle_found = _inner_bellman_ford(
  1072. G,
  1073. source,
  1074. weight,
  1075. pred,
  1076. dist,
  1077. heuristic,
  1078. )
  1079. if negative_cycle_found is not None:
  1080. raise nx.NetworkXUnbounded("Negative cycle detected.")
  1081. if paths is not None:
  1082. sources = set(source)
  1083. dsts = [target] if target is not None else pred
  1084. for dst in dsts:
  1085. gen = _build_paths_from_predecessors(sources, dst, pred)
  1086. paths[dst] = next(gen)
  1087. return dist
  1088. def _inner_bellman_ford(
  1089. G,
  1090. sources,
  1091. weight,
  1092. pred,
  1093. dist=None,
  1094. heuristic=True,
  1095. ):
  1096. """Inner Relaxation loop for Bellman–Ford algorithm.
  1097. This is an implementation of the SPFA variant.
  1098. See https://en.wikipedia.org/wiki/Shortest_Path_Faster_Algorithm
  1099. Parameters
  1100. ----------
  1101. G : NetworkX graph
  1102. source: list
  1103. List of source nodes. The shortest path from any of the source
  1104. nodes will be found if multiple sources are provided.
  1105. weight : function
  1106. The weight of an edge is the value returned by the function. The
  1107. function must accept exactly three positional arguments: the two
  1108. endpoints of an edge and the dictionary of edge attributes for
  1109. that edge. The function must return a number.
  1110. pred: dict of lists
  1111. dict to store a list of predecessors keyed by that node
  1112. dist: dict, optional (default=None)
  1113. dict to store distance from source to the keyed node
  1114. If None, returned dist dict contents default to 0 for every node in the
  1115. source list
  1116. heuristic : bool
  1117. Determines whether to use a heuristic to early detect negative
  1118. cycles at a hopefully negligible cost.
  1119. Returns
  1120. -------
  1121. node or None
  1122. Return a node `v` where processing discovered a negative cycle.
  1123. If no negative cycle found, return None.
  1124. Raises
  1125. ------
  1126. NodeNotFound
  1127. If any of `source` is not in `G`.
  1128. """
  1129. for s in sources:
  1130. if s not in G:
  1131. raise nx.NodeNotFound(f"Source {s} not in G")
  1132. if pred is None:
  1133. pred = {v: [] for v in sources}
  1134. if dist is None:
  1135. dist = {v: 0 for v in sources}
  1136. # Heuristic Storage setup. Note: use None because nodes cannot be None
  1137. nonexistent_edge = (None, None)
  1138. pred_edge = {v: None for v in sources}
  1139. recent_update = {v: nonexistent_edge for v in sources}
  1140. G_succ = G._adj # For speed-up (and works for both directed and undirected graphs)
  1141. inf = float("inf")
  1142. n = len(G)
  1143. count = {}
  1144. q = deque(sources)
  1145. in_q = set(sources)
  1146. while q:
  1147. u = q.popleft()
  1148. in_q.remove(u)
  1149. # Skip relaxations if any of the predecessors of u is in the queue.
  1150. if all(pred_u not in in_q for pred_u in pred[u]):
  1151. dist_u = dist[u]
  1152. for v, e in G_succ[u].items():
  1153. dist_v = dist_u + weight(u, v, e)
  1154. if dist_v < dist.get(v, inf):
  1155. # In this conditional branch we are updating the path with v.
  1156. # If it happens that some earlier update also added node v
  1157. # that implies the existence of a negative cycle since
  1158. # after the update node v would lie on the update path twice.
  1159. # The update path is stored up to one of the source nodes,
  1160. # therefore u is always in the dict recent_update
  1161. if heuristic:
  1162. if v in recent_update[u]:
  1163. # Negative cycle found!
  1164. pred[v].append(u)
  1165. return v
  1166. # Transfer the recent update info from u to v if the
  1167. # same source node is the head of the update path.
  1168. # If the source node is responsible for the cost update,
  1169. # then clear the history and use it instead.
  1170. if v in pred_edge and pred_edge[v] == u:
  1171. recent_update[v] = recent_update[u]
  1172. else:
  1173. recent_update[v] = (u, v)
  1174. if v not in in_q:
  1175. q.append(v)
  1176. in_q.add(v)
  1177. count_v = count.get(v, 0) + 1
  1178. if count_v == n:
  1179. # Negative cycle found!
  1180. return v
  1181. count[v] = count_v
  1182. dist[v] = dist_v
  1183. pred[v] = [u]
  1184. pred_edge[v] = u
  1185. elif dist.get(v) is not None and dist_v == dist.get(v):
  1186. pred[v].append(u)
  1187. # successfully found shortest_path. No negative cycles found.
  1188. return None
  1189. @nx._dispatch
  1190. def bellman_ford_path(G, source, target, weight="weight"):
  1191. """Returns the shortest path from source to target in a weighted graph G.
  1192. Parameters
  1193. ----------
  1194. G : NetworkX graph
  1195. source : node
  1196. Starting node
  1197. target : node
  1198. Ending node
  1199. weight : string or function (default="weight")
  1200. If this is a string, then edge weights will be accessed via the
  1201. edge attribute with this key (that is, the weight of the edge
  1202. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1203. such edge attribute exists, the weight of the edge is assumed to
  1204. be one.
  1205. If this is a function, the weight of an edge is the value
  1206. returned by the function. The function must accept exactly three
  1207. positional arguments: the two endpoints of an edge and the
  1208. dictionary of edge attributes for that edge. The function must
  1209. return a number.
  1210. Returns
  1211. -------
  1212. path : list
  1213. List of nodes in a shortest path.
  1214. Raises
  1215. ------
  1216. NodeNotFound
  1217. If `source` is not in `G`.
  1218. NetworkXNoPath
  1219. If no path exists between source and target.
  1220. Examples
  1221. --------
  1222. >>> G = nx.path_graph(5)
  1223. >>> nx.bellman_ford_path(G, 0, 4)
  1224. [0, 1, 2, 3, 4]
  1225. Notes
  1226. -----
  1227. Edge weight attributes must be numerical.
  1228. Distances are calculated as sums of weighted edges traversed.
  1229. See Also
  1230. --------
  1231. dijkstra_path, bellman_ford_path_length
  1232. """
  1233. length, path = single_source_bellman_ford(G, source, target=target, weight=weight)
  1234. return path
  1235. @nx._dispatch
  1236. def bellman_ford_path_length(G, source, target, weight="weight"):
  1237. """Returns the shortest path length from source to target
  1238. in a weighted graph.
  1239. Parameters
  1240. ----------
  1241. G : NetworkX graph
  1242. source : node label
  1243. starting node for path
  1244. target : node label
  1245. ending node for path
  1246. weight : string or function (default="weight")
  1247. If this is a string, then edge weights will be accessed via the
  1248. edge attribute with this key (that is, the weight of the edge
  1249. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1250. such edge attribute exists, the weight of the edge is assumed to
  1251. be one.
  1252. If this is a function, the weight of an edge is the value
  1253. returned by the function. The function must accept exactly three
  1254. positional arguments: the two endpoints of an edge and the
  1255. dictionary of edge attributes for that edge. The function must
  1256. return a number.
  1257. Returns
  1258. -------
  1259. length : number
  1260. Shortest path length.
  1261. Raises
  1262. ------
  1263. NodeNotFound
  1264. If `source` is not in `G`.
  1265. NetworkXNoPath
  1266. If no path exists between source and target.
  1267. Examples
  1268. --------
  1269. >>> G = nx.path_graph(5)
  1270. >>> nx.bellman_ford_path_length(G, 0, 4)
  1271. 4
  1272. Notes
  1273. -----
  1274. Edge weight attributes must be numerical.
  1275. Distances are calculated as sums of weighted edges traversed.
  1276. See Also
  1277. --------
  1278. dijkstra_path_length, bellman_ford_path
  1279. """
  1280. if source == target:
  1281. if source not in G:
  1282. raise nx.NodeNotFound(f"Node {source} not found in graph")
  1283. return 0
  1284. weight = _weight_function(G, weight)
  1285. length = _bellman_ford(G, [source], weight, target=target)
  1286. try:
  1287. return length[target]
  1288. except KeyError as err:
  1289. raise nx.NetworkXNoPath(f"node {target} not reachable from {source}") from err
  1290. @nx._dispatch
  1291. def single_source_bellman_ford_path(G, source, weight="weight"):
  1292. """Compute shortest path between source and all other reachable
  1293. nodes for a weighted graph.
  1294. Parameters
  1295. ----------
  1296. G : NetworkX graph
  1297. source : node
  1298. Starting node for path.
  1299. weight : string or function (default="weight")
  1300. If this is a string, then edge weights will be accessed via the
  1301. edge attribute with this key (that is, the weight of the edge
  1302. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1303. such edge attribute exists, the weight of the edge is assumed to
  1304. be one.
  1305. If this is a function, the weight of an edge is the value
  1306. returned by the function. The function must accept exactly three
  1307. positional arguments: the two endpoints of an edge and the
  1308. dictionary of edge attributes for that edge. The function must
  1309. return a number.
  1310. Returns
  1311. -------
  1312. paths : dictionary
  1313. Dictionary of shortest path lengths keyed by target.
  1314. Raises
  1315. ------
  1316. NodeNotFound
  1317. If `source` is not in `G`.
  1318. Examples
  1319. --------
  1320. >>> G = nx.path_graph(5)
  1321. >>> path = nx.single_source_bellman_ford_path(G, 0)
  1322. >>> path[4]
  1323. [0, 1, 2, 3, 4]
  1324. Notes
  1325. -----
  1326. Edge weight attributes must be numerical.
  1327. Distances are calculated as sums of weighted edges traversed.
  1328. See Also
  1329. --------
  1330. single_source_dijkstra, single_source_bellman_ford
  1331. """
  1332. (length, path) = single_source_bellman_ford(G, source, weight=weight)
  1333. return path
  1334. @nx._dispatch
  1335. def single_source_bellman_ford_path_length(G, source, weight="weight"):
  1336. """Compute the shortest path length between source and all other
  1337. reachable nodes for a weighted graph.
  1338. Parameters
  1339. ----------
  1340. G : NetworkX graph
  1341. source : node label
  1342. Starting node for path
  1343. weight : string or function (default="weight")
  1344. If this is a string, then edge weights will be accessed via the
  1345. edge attribute with this key (that is, the weight of the edge
  1346. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1347. such edge attribute exists, the weight of the edge is assumed to
  1348. be one.
  1349. If this is a function, the weight of an edge is the value
  1350. returned by the function. The function must accept exactly three
  1351. positional arguments: the two endpoints of an edge and the
  1352. dictionary of edge attributes for that edge. The function must
  1353. return a number.
  1354. Returns
  1355. -------
  1356. length : dictionary
  1357. Dictionary of shortest path length keyed by target
  1358. Raises
  1359. ------
  1360. NodeNotFound
  1361. If `source` is not in `G`.
  1362. Examples
  1363. --------
  1364. >>> G = nx.path_graph(5)
  1365. >>> length = nx.single_source_bellman_ford_path_length(G, 0)
  1366. >>> length[4]
  1367. 4
  1368. >>> for node in [0, 1, 2, 3, 4]:
  1369. ... print(f"{node}: {length[node]}")
  1370. 0: 0
  1371. 1: 1
  1372. 2: 2
  1373. 3: 3
  1374. 4: 4
  1375. Notes
  1376. -----
  1377. Edge weight attributes must be numerical.
  1378. Distances are calculated as sums of weighted edges traversed.
  1379. See Also
  1380. --------
  1381. single_source_dijkstra, single_source_bellman_ford
  1382. """
  1383. weight = _weight_function(G, weight)
  1384. return _bellman_ford(G, [source], weight)
  1385. @nx._dispatch
  1386. def single_source_bellman_ford(G, source, target=None, weight="weight"):
  1387. """Compute shortest paths and lengths in a weighted graph G.
  1388. Uses Bellman-Ford algorithm for shortest paths.
  1389. Parameters
  1390. ----------
  1391. G : NetworkX graph
  1392. source : node label
  1393. Starting node for path
  1394. target : node label, optional
  1395. Ending node for path
  1396. weight : string or function
  1397. If this is a string, then edge weights will be accessed via the
  1398. edge attribute with this key (that is, the weight of the edge
  1399. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1400. such edge attribute exists, the weight of the edge is assumed to
  1401. be one.
  1402. If this is a function, the weight of an edge is the value
  1403. returned by the function. The function must accept exactly three
  1404. positional arguments: the two endpoints of an edge and the
  1405. dictionary of edge attributes for that edge. The function must
  1406. return a number.
  1407. Returns
  1408. -------
  1409. distance, path : pair of dictionaries, or numeric and list
  1410. If target is None, returns a tuple of two dictionaries keyed by node.
  1411. The first dictionary stores distance from one of the source nodes.
  1412. The second stores the path from one of the sources to that node.
  1413. If target is not None, returns a tuple of (distance, path) where
  1414. distance is the distance from source to target and path is a list
  1415. representing the path from source to target.
  1416. Raises
  1417. ------
  1418. NodeNotFound
  1419. If `source` is not in `G`.
  1420. Examples
  1421. --------
  1422. >>> G = nx.path_graph(5)
  1423. >>> length, path = nx.single_source_bellman_ford(G, 0)
  1424. >>> length[4]
  1425. 4
  1426. >>> for node in [0, 1, 2, 3, 4]:
  1427. ... print(f"{node}: {length[node]}")
  1428. 0: 0
  1429. 1: 1
  1430. 2: 2
  1431. 3: 3
  1432. 4: 4
  1433. >>> path[4]
  1434. [0, 1, 2, 3, 4]
  1435. >>> length, path = nx.single_source_bellman_ford(G, 0, 1)
  1436. >>> length
  1437. 1
  1438. >>> path
  1439. [0, 1]
  1440. Notes
  1441. -----
  1442. Edge weight attributes must be numerical.
  1443. Distances are calculated as sums of weighted edges traversed.
  1444. See Also
  1445. --------
  1446. single_source_dijkstra
  1447. single_source_bellman_ford_path
  1448. single_source_bellman_ford_path_length
  1449. """
  1450. if source == target:
  1451. if source not in G:
  1452. raise nx.NodeNotFound(f"Node {source} is not found in the graph")
  1453. return (0, [source])
  1454. weight = _weight_function(G, weight)
  1455. paths = {source: [source]} # dictionary of paths
  1456. dist = _bellman_ford(G, [source], weight, paths=paths, target=target)
  1457. if target is None:
  1458. return (dist, paths)
  1459. try:
  1460. return (dist[target], paths[target])
  1461. except KeyError as err:
  1462. msg = f"Node {target} not reachable from {source}"
  1463. raise nx.NetworkXNoPath(msg) from err
  1464. @nx._dispatch
  1465. def all_pairs_bellman_ford_path_length(G, weight="weight"):
  1466. """Compute shortest path lengths between all nodes in a weighted graph.
  1467. Parameters
  1468. ----------
  1469. G : NetworkX graph
  1470. weight : string or function (default="weight")
  1471. If this is a string, then edge weights will be accessed via the
  1472. edge attribute with this key (that is, the weight of the edge
  1473. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1474. such edge attribute exists, the weight of the edge is assumed to
  1475. be one.
  1476. If this is a function, the weight of an edge is the value
  1477. returned by the function. The function must accept exactly three
  1478. positional arguments: the two endpoints of an edge and the
  1479. dictionary of edge attributes for that edge. The function must
  1480. return a number.
  1481. Returns
  1482. -------
  1483. distance : iterator
  1484. (source, dictionary) iterator with dictionary keyed by target and
  1485. shortest path length as the key value.
  1486. Examples
  1487. --------
  1488. >>> G = nx.path_graph(5)
  1489. >>> length = dict(nx.all_pairs_bellman_ford_path_length(G))
  1490. >>> for node in [0, 1, 2, 3, 4]:
  1491. ... print(f"1 - {node}: {length[1][node]}")
  1492. 1 - 0: 1
  1493. 1 - 1: 0
  1494. 1 - 2: 1
  1495. 1 - 3: 2
  1496. 1 - 4: 3
  1497. >>> length[3][2]
  1498. 1
  1499. >>> length[2][2]
  1500. 0
  1501. Notes
  1502. -----
  1503. Edge weight attributes must be numerical.
  1504. Distances are calculated as sums of weighted edges traversed.
  1505. The dictionary returned only has keys for reachable node pairs.
  1506. """
  1507. length = single_source_bellman_ford_path_length
  1508. for n in G:
  1509. yield (n, dict(length(G, n, weight=weight)))
  1510. @nx._dispatch
  1511. def all_pairs_bellman_ford_path(G, weight="weight"):
  1512. """Compute shortest paths between all nodes in a weighted graph.
  1513. Parameters
  1514. ----------
  1515. G : NetworkX graph
  1516. weight : string or function (default="weight")
  1517. If this is a string, then edge weights will be accessed via the
  1518. edge attribute with this key (that is, the weight of the edge
  1519. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1520. such edge attribute exists, the weight of the edge is assumed to
  1521. be one.
  1522. If this is a function, the weight of an edge is the value
  1523. returned by the function. The function must accept exactly three
  1524. positional arguments: the two endpoints of an edge and the
  1525. dictionary of edge attributes for that edge. The function must
  1526. return a number.
  1527. Returns
  1528. -------
  1529. paths : iterator
  1530. (source, dictionary) iterator with dictionary keyed by target and
  1531. shortest path as the key value.
  1532. Examples
  1533. --------
  1534. >>> G = nx.path_graph(5)
  1535. >>> path = dict(nx.all_pairs_bellman_ford_path(G))
  1536. >>> path[0][4]
  1537. [0, 1, 2, 3, 4]
  1538. Notes
  1539. -----
  1540. Edge weight attributes must be numerical.
  1541. Distances are calculated as sums of weighted edges traversed.
  1542. See Also
  1543. --------
  1544. floyd_warshall, all_pairs_dijkstra_path
  1545. """
  1546. path = single_source_bellman_ford_path
  1547. # TODO This can be trivially parallelized.
  1548. for n in G:
  1549. yield (n, path(G, n, weight=weight))
  1550. def goldberg_radzik(G, source, weight="weight"):
  1551. """Compute shortest path lengths and predecessors on shortest paths
  1552. in weighted graphs.
  1553. The algorithm has a running time of $O(mn)$ where $n$ is the number of
  1554. nodes and $m$ is the number of edges. It is slower than Dijkstra but
  1555. can handle negative edge weights.
  1556. Parameters
  1557. ----------
  1558. G : NetworkX graph
  1559. The algorithm works for all types of graphs, including directed
  1560. graphs and multigraphs.
  1561. source: node label
  1562. Starting node for path
  1563. weight : string or function
  1564. If this is a string, then edge weights will be accessed via the
  1565. edge attribute with this key (that is, the weight of the edge
  1566. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1567. such edge attribute exists, the weight of the edge is assumed to
  1568. be one.
  1569. If this is a function, the weight of an edge is the value
  1570. returned by the function. The function must accept exactly three
  1571. positional arguments: the two endpoints of an edge and the
  1572. dictionary of edge attributes for that edge. The function must
  1573. return a number.
  1574. Returns
  1575. -------
  1576. pred, dist : dictionaries
  1577. Returns two dictionaries keyed by node to predecessor in the
  1578. path and to the distance from the source respectively.
  1579. Raises
  1580. ------
  1581. NodeNotFound
  1582. If `source` is not in `G`.
  1583. NetworkXUnbounded
  1584. If the (di)graph contains a negative (di)cycle, the
  1585. algorithm raises an exception to indicate the presence of the
  1586. negative (di)cycle. Note: any negative weight edge in an
  1587. undirected graph is a negative cycle.
  1588. Examples
  1589. --------
  1590. >>> G = nx.path_graph(5, create_using=nx.DiGraph())
  1591. >>> pred, dist = nx.goldberg_radzik(G, 0)
  1592. >>> sorted(pred.items())
  1593. [(0, None), (1, 0), (2, 1), (3, 2), (4, 3)]
  1594. >>> sorted(dist.items())
  1595. [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4)]
  1596. >>> G = nx.cycle_graph(5, create_using=nx.DiGraph())
  1597. >>> G[1][2]["weight"] = -7
  1598. >>> nx.goldberg_radzik(G, 0)
  1599. Traceback (most recent call last):
  1600. ...
  1601. networkx.exception.NetworkXUnbounded: Negative cycle detected.
  1602. Notes
  1603. -----
  1604. Edge weight attributes must be numerical.
  1605. Distances are calculated as sums of weighted edges traversed.
  1606. The dictionaries returned only have keys for nodes reachable from
  1607. the source.
  1608. In the case where the (di)graph is not connected, if a component
  1609. not containing the source contains a negative (di)cycle, it
  1610. will not be detected.
  1611. """
  1612. if source not in G:
  1613. raise nx.NodeNotFound(f"Node {source} is not found in the graph")
  1614. weight = _weight_function(G, weight)
  1615. if any(weight(u, v, d) < 0 for u, v, d in nx.selfloop_edges(G, data=True)):
  1616. raise nx.NetworkXUnbounded("Negative cycle detected.")
  1617. if len(G) == 1:
  1618. return {source: None}, {source: 0}
  1619. G_succ = G._adj # For speed-up (and works for both directed and undirected graphs)
  1620. inf = float("inf")
  1621. d = {u: inf for u in G}
  1622. d[source] = 0
  1623. pred = {source: None}
  1624. def topo_sort(relabeled):
  1625. """Topologically sort nodes relabeled in the previous round and detect
  1626. negative cycles.
  1627. """
  1628. # List of nodes to scan in this round. Denoted by A in Goldberg and
  1629. # Radzik's paper.
  1630. to_scan = []
  1631. # In the DFS in the loop below, neg_count records for each node the
  1632. # number of edges of negative reduced costs on the path from a DFS root
  1633. # to the node in the DFS forest. The reduced cost of an edge (u, v) is
  1634. # defined as d[u] + weight[u][v] - d[v].
  1635. #
  1636. # neg_count also doubles as the DFS visit marker array.
  1637. neg_count = {}
  1638. for u in relabeled:
  1639. # Skip visited nodes.
  1640. if u in neg_count:
  1641. continue
  1642. d_u = d[u]
  1643. # Skip nodes without out-edges of negative reduced costs.
  1644. if all(d_u + weight(u, v, e) >= d[v] for v, e in G_succ[u].items()):
  1645. continue
  1646. # Nonrecursive DFS that inserts nodes reachable from u via edges of
  1647. # nonpositive reduced costs into to_scan in (reverse) topological
  1648. # order.
  1649. stack = [(u, iter(G_succ[u].items()))]
  1650. in_stack = {u}
  1651. neg_count[u] = 0
  1652. while stack:
  1653. u, it = stack[-1]
  1654. try:
  1655. v, e = next(it)
  1656. except StopIteration:
  1657. to_scan.append(u)
  1658. stack.pop()
  1659. in_stack.remove(u)
  1660. continue
  1661. t = d[u] + weight(u, v, e)
  1662. d_v = d[v]
  1663. if t <= d_v:
  1664. is_neg = t < d_v
  1665. d[v] = t
  1666. pred[v] = u
  1667. if v not in neg_count:
  1668. neg_count[v] = neg_count[u] + int(is_neg)
  1669. stack.append((v, iter(G_succ[v].items())))
  1670. in_stack.add(v)
  1671. elif v in in_stack and neg_count[u] + int(is_neg) > neg_count[v]:
  1672. # (u, v) is a back edge, and the cycle formed by the
  1673. # path v to u and (u, v) contains at least one edge of
  1674. # negative reduced cost. The cycle must be of negative
  1675. # cost.
  1676. raise nx.NetworkXUnbounded("Negative cycle detected.")
  1677. to_scan.reverse()
  1678. return to_scan
  1679. def relax(to_scan):
  1680. """Relax out-edges of relabeled nodes."""
  1681. relabeled = set()
  1682. # Scan nodes in to_scan in topological order and relax incident
  1683. # out-edges. Add the relabled nodes to labeled.
  1684. for u in to_scan:
  1685. d_u = d[u]
  1686. for v, e in G_succ[u].items():
  1687. w_e = weight(u, v, e)
  1688. if d_u + w_e < d[v]:
  1689. d[v] = d_u + w_e
  1690. pred[v] = u
  1691. relabeled.add(v)
  1692. return relabeled
  1693. # Set of nodes relabled in the last round of scan operations. Denoted by B
  1694. # in Goldberg and Radzik's paper.
  1695. relabeled = {source}
  1696. while relabeled:
  1697. to_scan = topo_sort(relabeled)
  1698. relabeled = relax(to_scan)
  1699. d = {u: d[u] for u in pred}
  1700. return pred, d
  1701. @nx._dispatch
  1702. def negative_edge_cycle(G, weight="weight", heuristic=True):
  1703. """Returns True if there exists a negative edge cycle anywhere in G.
  1704. Parameters
  1705. ----------
  1706. G : NetworkX graph
  1707. weight : string or function
  1708. If this is a string, then edge weights will be accessed via the
  1709. edge attribute with this key (that is, the weight of the edge
  1710. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1711. such edge attribute exists, the weight of the edge is assumed to
  1712. be one.
  1713. If this is a function, the weight of an edge is the value
  1714. returned by the function. The function must accept exactly three
  1715. positional arguments: the two endpoints of an edge and the
  1716. dictionary of edge attributes for that edge. The function must
  1717. return a number.
  1718. heuristic : bool
  1719. Determines whether to use a heuristic to early detect negative
  1720. cycles at a negligible cost. In case of graphs with a negative cycle,
  1721. the performance of detection increases by at least an order of magnitude.
  1722. Returns
  1723. -------
  1724. negative_cycle : bool
  1725. True if a negative edge cycle exists, otherwise False.
  1726. Examples
  1727. --------
  1728. >>> G = nx.cycle_graph(5, create_using=nx.DiGraph())
  1729. >>> print(nx.negative_edge_cycle(G))
  1730. False
  1731. >>> G[1][2]["weight"] = -7
  1732. >>> print(nx.negative_edge_cycle(G))
  1733. True
  1734. Notes
  1735. -----
  1736. Edge weight attributes must be numerical.
  1737. Distances are calculated as sums of weighted edges traversed.
  1738. This algorithm uses bellman_ford_predecessor_and_distance() but finds
  1739. negative cycles on any component by first adding a new node connected to
  1740. every node, and starting bellman_ford_predecessor_and_distance on that
  1741. node. It then removes that extra node.
  1742. """
  1743. if G.size() == 0:
  1744. return False
  1745. # find unused node to use temporarily
  1746. newnode = -1
  1747. while newnode in G:
  1748. newnode -= 1
  1749. # connect it to all nodes
  1750. G.add_edges_from([(newnode, n) for n in G])
  1751. try:
  1752. bellman_ford_predecessor_and_distance(
  1753. G, newnode, weight=weight, heuristic=heuristic
  1754. )
  1755. except nx.NetworkXUnbounded:
  1756. return True
  1757. finally:
  1758. G.remove_node(newnode)
  1759. return False
  1760. def find_negative_cycle(G, source, weight="weight"):
  1761. """Returns a cycle with negative total weight if it exists.
  1762. Bellman-Ford is used to find shortest_paths. That algorithm
  1763. stops if there exists a negative cycle. This algorithm
  1764. picks up from there and returns the found negative cycle.
  1765. The cycle consists of a list of nodes in the cycle order. The last
  1766. node equals the first to make it a cycle.
  1767. You can look up the edge weights in the original graph. In the case
  1768. of multigraphs the relevant edge is the minimal weight edge between
  1769. the nodes in the 2-tuple.
  1770. If the graph has no negative cycle, a NetworkXError is raised.
  1771. Parameters
  1772. ----------
  1773. G : NetworkX graph
  1774. source: node label
  1775. The search for the negative cycle will start from this node.
  1776. weight : string or function
  1777. If this is a string, then edge weights will be accessed via the
  1778. edge attribute with this key (that is, the weight of the edge
  1779. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1780. such edge attribute exists, the weight of the edge is assumed to
  1781. be one.
  1782. If this is a function, the weight of an edge is the value
  1783. returned by the function. The function must accept exactly three
  1784. positional arguments: the two endpoints of an edge and the
  1785. dictionary of edge attributes for that edge. The function must
  1786. return a number.
  1787. Examples
  1788. --------
  1789. >>> G = nx.DiGraph()
  1790. >>> G.add_weighted_edges_from([(0, 1, 2), (1, 2, 2), (2, 0, 1), (1, 4, 2), (4, 0, -5)])
  1791. >>> nx.find_negative_cycle(G, 0)
  1792. [4, 0, 1, 4]
  1793. Returns
  1794. -------
  1795. cycle : list
  1796. A list of nodes in the order of the cycle found. The last node
  1797. equals the first to indicate a cycle.
  1798. Raises
  1799. ------
  1800. NetworkXError
  1801. If no negative cycle is found.
  1802. """
  1803. weight = _weight_function(G, weight)
  1804. pred = {source: []}
  1805. v = _inner_bellman_ford(G, [source], weight, pred=pred)
  1806. if v is None:
  1807. raise nx.NetworkXError("No negative cycles detected.")
  1808. # negative cycle detected... find it
  1809. neg_cycle = []
  1810. stack = [(v, list(pred[v]))]
  1811. seen = {v}
  1812. while stack:
  1813. node, preds = stack[-1]
  1814. if v in preds:
  1815. # found the cycle
  1816. neg_cycle.extend([node, v])
  1817. neg_cycle = list(reversed(neg_cycle))
  1818. return neg_cycle
  1819. if preds:
  1820. nbr = preds.pop()
  1821. if nbr not in seen:
  1822. stack.append((nbr, list(pred[nbr])))
  1823. neg_cycle.append(node)
  1824. seen.add(nbr)
  1825. else:
  1826. stack.pop()
  1827. if neg_cycle:
  1828. neg_cycle.pop()
  1829. else:
  1830. if v in G[v] and weight(G, v, v) < 0:
  1831. return [v, v]
  1832. # should not reach here
  1833. raise nx.NetworkXError("Negative cycle is detected but not found")
  1834. # should not get here...
  1835. msg = "negative cycle detected but not identified"
  1836. raise nx.NetworkXUnbounded(msg)
  1837. def bidirectional_dijkstra(G, source, target, weight="weight"):
  1838. r"""Dijkstra's algorithm for shortest paths using bidirectional search.
  1839. Parameters
  1840. ----------
  1841. G : NetworkX graph
  1842. source : node
  1843. Starting node.
  1844. target : node
  1845. Ending node.
  1846. weight : string or function
  1847. If this is a string, then edge weights will be accessed via the
  1848. edge attribute with this key (that is, the weight of the edge
  1849. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1850. such edge attribute exists, the weight of the edge is assumed to
  1851. be one.
  1852. If this is a function, the weight of an edge is the value
  1853. returned by the function. The function must accept exactly three
  1854. positional arguments: the two endpoints of an edge and the
  1855. dictionary of edge attributes for that edge. The function must
  1856. return a number or None to indicate a hidden edge.
  1857. Returns
  1858. -------
  1859. length, path : number and list
  1860. length is the distance from source to target.
  1861. path is a list of nodes on a path from source to target.
  1862. Raises
  1863. ------
  1864. NodeNotFound
  1865. If either `source` or `target` is not in `G`.
  1866. NetworkXNoPath
  1867. If no path exists between source and target.
  1868. Examples
  1869. --------
  1870. >>> G = nx.path_graph(5)
  1871. >>> length, path = nx.bidirectional_dijkstra(G, 0, 4)
  1872. >>> print(length)
  1873. 4
  1874. >>> print(path)
  1875. [0, 1, 2, 3, 4]
  1876. Notes
  1877. -----
  1878. Edge weight attributes must be numerical.
  1879. Distances are calculated as sums of weighted edges traversed.
  1880. The weight function can be used to hide edges by returning None.
  1881. So ``weight = lambda u, v, d: 1 if d['color']=="red" else None``
  1882. will find the shortest red path.
  1883. In practice bidirectional Dijkstra is much more than twice as fast as
  1884. ordinary Dijkstra.
  1885. Ordinary Dijkstra expands nodes in a sphere-like manner from the
  1886. source. The radius of this sphere will eventually be the length
  1887. of the shortest path. Bidirectional Dijkstra will expand nodes
  1888. from both the source and the target, making two spheres of half
  1889. this radius. Volume of the first sphere is `\pi*r*r` while the
  1890. others are `2*\pi*r/2*r/2`, making up half the volume.
  1891. This algorithm is not guaranteed to work if edge weights
  1892. are negative or are floating point numbers
  1893. (overflows and roundoff errors can cause problems).
  1894. See Also
  1895. --------
  1896. shortest_path
  1897. shortest_path_length
  1898. """
  1899. if source not in G or target not in G:
  1900. msg = f"Either source {source} or target {target} is not in G"
  1901. raise nx.NodeNotFound(msg)
  1902. if source == target:
  1903. return (0, [source])
  1904. weight = _weight_function(G, weight)
  1905. push = heappush
  1906. pop = heappop
  1907. # Init: [Forward, Backward]
  1908. dists = [{}, {}] # dictionary of final distances
  1909. paths = [{source: [source]}, {target: [target]}] # dictionary of paths
  1910. fringe = [[], []] # heap of (distance, node) for choosing node to expand
  1911. seen = [{source: 0}, {target: 0}] # dict of distances to seen nodes
  1912. c = count()
  1913. # initialize fringe heap
  1914. push(fringe[0], (0, next(c), source))
  1915. push(fringe[1], (0, next(c), target))
  1916. # neighs for extracting correct neighbor information
  1917. if G.is_directed():
  1918. neighs = [G._succ, G._pred]
  1919. else:
  1920. neighs = [G._adj, G._adj]
  1921. # variables to hold shortest discovered path
  1922. # finaldist = 1e30000
  1923. finalpath = []
  1924. dir = 1
  1925. while fringe[0] and fringe[1]:
  1926. # choose direction
  1927. # dir == 0 is forward direction and dir == 1 is back
  1928. dir = 1 - dir
  1929. # extract closest to expand
  1930. (dist, _, v) = pop(fringe[dir])
  1931. if v in dists[dir]:
  1932. # Shortest path to v has already been found
  1933. continue
  1934. # update distance
  1935. dists[dir][v] = dist # equal to seen[dir][v]
  1936. if v in dists[1 - dir]:
  1937. # if we have scanned v in both directions we are done
  1938. # we have now discovered the shortest path
  1939. return (finaldist, finalpath)
  1940. for w, d in neighs[dir][v].items():
  1941. # weight(v, w, d) for forward and weight(w, v, d) for back direction
  1942. cost = weight(v, w, d) if dir == 0 else weight(w, v, d)
  1943. if cost is None:
  1944. continue
  1945. vwLength = dists[dir][v] + cost
  1946. if w in dists[dir]:
  1947. if vwLength < dists[dir][w]:
  1948. raise ValueError("Contradictory paths found: negative weights?")
  1949. elif w not in seen[dir] or vwLength < seen[dir][w]:
  1950. # relaxing
  1951. seen[dir][w] = vwLength
  1952. push(fringe[dir], (vwLength, next(c), w))
  1953. paths[dir][w] = paths[dir][v] + [w]
  1954. if w in seen[0] and w in seen[1]:
  1955. # see if this path is better than the already
  1956. # discovered shortest path
  1957. totaldist = seen[0][w] + seen[1][w]
  1958. if finalpath == [] or finaldist > totaldist:
  1959. finaldist = totaldist
  1960. revpath = paths[1][w][:]
  1961. revpath.reverse()
  1962. finalpath = paths[0][w] + revpath[1:]
  1963. raise nx.NetworkXNoPath(f"No path between {source} and {target}.")
  1964. def johnson(G, weight="weight"):
  1965. r"""Uses Johnson's Algorithm to compute shortest paths.
  1966. Johnson's Algorithm finds a shortest path between each pair of
  1967. nodes in a weighted graph even if negative weights are present.
  1968. Parameters
  1969. ----------
  1970. G : NetworkX graph
  1971. weight : string or function
  1972. If this is a string, then edge weights will be accessed via the
  1973. edge attribute with this key (that is, the weight of the edge
  1974. joining `u` to `v` will be ``G.edges[u, v][weight]``). If no
  1975. such edge attribute exists, the weight of the edge is assumed to
  1976. be one.
  1977. If this is a function, the weight of an edge is the value
  1978. returned by the function. The function must accept exactly three
  1979. positional arguments: the two endpoints of an edge and the
  1980. dictionary of edge attributes for that edge. The function must
  1981. return a number.
  1982. Returns
  1983. -------
  1984. distance : dictionary
  1985. Dictionary, keyed by source and target, of shortest paths.
  1986. Raises
  1987. ------
  1988. NetworkXError
  1989. If given graph is not weighted.
  1990. Examples
  1991. --------
  1992. >>> graph = nx.DiGraph()
  1993. >>> graph.add_weighted_edges_from(
  1994. ... [("0", "3", 3), ("0", "1", -5), ("0", "2", 2), ("1", "2", 4), ("2", "3", 1)]
  1995. ... )
  1996. >>> paths = nx.johnson(graph, weight="weight")
  1997. >>> paths["0"]["2"]
  1998. ['0', '1', '2']
  1999. Notes
  2000. -----
  2001. Johnson's algorithm is suitable even for graphs with negative weights. It
  2002. works by using the Bellman–Ford algorithm to compute a transformation of
  2003. the input graph that removes all negative weights, allowing Dijkstra's
  2004. algorithm to be used on the transformed graph.
  2005. The time complexity of this algorithm is $O(n^2 \log n + n m)$,
  2006. where $n$ is the number of nodes and $m$ the number of edges in the
  2007. graph. For dense graphs, this may be faster than the Floyd–Warshall
  2008. algorithm.
  2009. See Also
  2010. --------
  2011. floyd_warshall_predecessor_and_distance
  2012. floyd_warshall_numpy
  2013. all_pairs_shortest_path
  2014. all_pairs_shortest_path_length
  2015. all_pairs_dijkstra_path
  2016. bellman_ford_predecessor_and_distance
  2017. all_pairs_bellman_ford_path
  2018. all_pairs_bellman_ford_path_length
  2019. """
  2020. if not nx.is_weighted(G, weight=weight):
  2021. raise nx.NetworkXError("Graph is not weighted.")
  2022. dist = {v: 0 for v in G}
  2023. pred = {v: [] for v in G}
  2024. weight = _weight_function(G, weight)
  2025. # Calculate distance of shortest paths
  2026. dist_bellman = _bellman_ford(G, list(G), weight, pred=pred, dist=dist)
  2027. # Update the weight function to take into account the Bellman--Ford
  2028. # relaxation distances.
  2029. def new_weight(u, v, d):
  2030. return weight(u, v, d) + dist_bellman[u] - dist_bellman[v]
  2031. def dist_path(v):
  2032. paths = {v: [v]}
  2033. _dijkstra(G, v, new_weight, paths=paths)
  2034. return paths
  2035. return {v: dist_path(v) for v in G}