maxflow.py 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603
  1. """
  2. Maximum flow (and minimum cut) algorithms on capacitated graphs.
  3. """
  4. import networkx as nx
  5. from .boykovkolmogorov import boykov_kolmogorov
  6. from .dinitz_alg import dinitz
  7. from .edmondskarp import edmonds_karp
  8. from .preflowpush import preflow_push
  9. from .shortestaugmentingpath import shortest_augmenting_path
  10. from .utils import build_flow_dict
  11. # Define the default flow function for computing maximum flow.
  12. default_flow_func = preflow_push
  13. __all__ = ["maximum_flow", "maximum_flow_value", "minimum_cut", "minimum_cut_value"]
  14. def maximum_flow(flowG, _s, _t, capacity="capacity", flow_func=None, **kwargs):
  15. """Find a maximum single-commodity flow.
  16. Parameters
  17. ----------
  18. flowG : NetworkX graph
  19. Edges of the graph are expected to have an attribute called
  20. 'capacity'. If this attribute is not present, the edge is
  21. considered to have infinite capacity.
  22. _s : node
  23. Source node for the flow.
  24. _t : node
  25. Sink node for the flow.
  26. capacity : string
  27. Edges of the graph G are expected to have an attribute capacity
  28. that indicates how much flow the edge can support. If this
  29. attribute is not present, the edge is considered to have
  30. infinite capacity. Default value: 'capacity'.
  31. flow_func : function
  32. A function for computing the maximum flow among a pair of nodes
  33. in a capacitated graph. The function has to accept at least three
  34. parameters: a Graph or Digraph, a source node, and a target node.
  35. And return a residual network that follows NetworkX conventions
  36. (see Notes). If flow_func is None, the default maximum
  37. flow function (:meth:`preflow_push`) is used. See below for
  38. alternative algorithms. The choice of the default function may change
  39. from version to version and should not be relied on. Default value:
  40. None.
  41. kwargs : Any other keyword parameter is passed to the function that
  42. computes the maximum flow.
  43. Returns
  44. -------
  45. flow_value : integer, float
  46. Value of the maximum flow, i.e., net outflow from the source.
  47. flow_dict : dict
  48. A dictionary containing the value of the flow that went through
  49. each edge.
  50. Raises
  51. ------
  52. NetworkXError
  53. The algorithm does not support MultiGraph and MultiDiGraph. If
  54. the input graph is an instance of one of these two classes, a
  55. NetworkXError is raised.
  56. NetworkXUnbounded
  57. If the graph has a path of infinite capacity, the value of a
  58. feasible flow on the graph is unbounded above and the function
  59. raises a NetworkXUnbounded.
  60. See also
  61. --------
  62. :meth:`maximum_flow_value`
  63. :meth:`minimum_cut`
  64. :meth:`minimum_cut_value`
  65. :meth:`edmonds_karp`
  66. :meth:`preflow_push`
  67. :meth:`shortest_augmenting_path`
  68. Notes
  69. -----
  70. The function used in the flow_func parameter has to return a residual
  71. network that follows NetworkX conventions:
  72. The residual network :samp:`R` from an input graph :samp:`G` has the
  73. same nodes as :samp:`G`. :samp:`R` is a DiGraph that contains a pair
  74. of edges :samp:`(u, v)` and :samp:`(v, u)` iff :samp:`(u, v)` is not a
  75. self-loop, and at least one of :samp:`(u, v)` and :samp:`(v, u)` exists
  76. in :samp:`G`.
  77. For each edge :samp:`(u, v)` in :samp:`R`, :samp:`R[u][v]['capacity']`
  78. is equal to the capacity of :samp:`(u, v)` in :samp:`G` if it exists
  79. in :samp:`G` or zero otherwise. If the capacity is infinite,
  80. :samp:`R[u][v]['capacity']` will have a high arbitrary finite value
  81. that does not affect the solution of the problem. This value is stored in
  82. :samp:`R.graph['inf']`. For each edge :samp:`(u, v)` in :samp:`R`,
  83. :samp:`R[u][v]['flow']` represents the flow function of :samp:`(u, v)` and
  84. satisfies :samp:`R[u][v]['flow'] == -R[v][u]['flow']`.
  85. The flow value, defined as the total flow into :samp:`t`, the sink, is
  86. stored in :samp:`R.graph['flow_value']`. Reachability to :samp:`t` using
  87. only edges :samp:`(u, v)` such that
  88. :samp:`R[u][v]['flow'] < R[u][v]['capacity']` induces a minimum
  89. :samp:`s`-:samp:`t` cut.
  90. Specific algorithms may store extra data in :samp:`R`.
  91. The function should supports an optional boolean parameter value_only. When
  92. True, it can optionally terminate the algorithm as soon as the maximum flow
  93. value and the minimum cut can be determined.
  94. Examples
  95. --------
  96. >>> G = nx.DiGraph()
  97. >>> G.add_edge("x", "a", capacity=3.0)
  98. >>> G.add_edge("x", "b", capacity=1.0)
  99. >>> G.add_edge("a", "c", capacity=3.0)
  100. >>> G.add_edge("b", "c", capacity=5.0)
  101. >>> G.add_edge("b", "d", capacity=4.0)
  102. >>> G.add_edge("d", "e", capacity=2.0)
  103. >>> G.add_edge("c", "y", capacity=2.0)
  104. >>> G.add_edge("e", "y", capacity=3.0)
  105. maximum_flow returns both the value of the maximum flow and a
  106. dictionary with all flows.
  107. >>> flow_value, flow_dict = nx.maximum_flow(G, "x", "y")
  108. >>> flow_value
  109. 3.0
  110. >>> print(flow_dict["x"]["b"])
  111. 1.0
  112. You can also use alternative algorithms for computing the
  113. maximum flow by using the flow_func parameter.
  114. >>> from networkx.algorithms.flow import shortest_augmenting_path
  115. >>> flow_value == nx.maximum_flow(G, "x", "y", flow_func=shortest_augmenting_path)[
  116. ... 0
  117. ... ]
  118. True
  119. """
  120. if flow_func is None:
  121. if kwargs:
  122. raise nx.NetworkXError(
  123. "You have to explicitly set a flow_func if"
  124. " you need to pass parameters via kwargs."
  125. )
  126. flow_func = default_flow_func
  127. if not callable(flow_func):
  128. raise nx.NetworkXError("flow_func has to be callable.")
  129. R = flow_func(flowG, _s, _t, capacity=capacity, value_only=False, **kwargs)
  130. flow_dict = build_flow_dict(flowG, R)
  131. return (R.graph["flow_value"], flow_dict)
  132. def maximum_flow_value(flowG, _s, _t, capacity="capacity", flow_func=None, **kwargs):
  133. """Find the value of maximum single-commodity flow.
  134. Parameters
  135. ----------
  136. flowG : NetworkX graph
  137. Edges of the graph are expected to have an attribute called
  138. 'capacity'. If this attribute is not present, the edge is
  139. considered to have infinite capacity.
  140. _s : node
  141. Source node for the flow.
  142. _t : node
  143. Sink node for the flow.
  144. capacity : string
  145. Edges of the graph G are expected to have an attribute capacity
  146. that indicates how much flow the edge can support. If this
  147. attribute is not present, the edge is considered to have
  148. infinite capacity. Default value: 'capacity'.
  149. flow_func : function
  150. A function for computing the maximum flow among a pair of nodes
  151. in a capacitated graph. The function has to accept at least three
  152. parameters: a Graph or Digraph, a source node, and a target node.
  153. And return a residual network that follows NetworkX conventions
  154. (see Notes). If flow_func is None, the default maximum
  155. flow function (:meth:`preflow_push`) is used. See below for
  156. alternative algorithms. The choice of the default function may change
  157. from version to version and should not be relied on. Default value:
  158. None.
  159. kwargs : Any other keyword parameter is passed to the function that
  160. computes the maximum flow.
  161. Returns
  162. -------
  163. flow_value : integer, float
  164. Value of the maximum flow, i.e., net outflow from the source.
  165. Raises
  166. ------
  167. NetworkXError
  168. The algorithm does not support MultiGraph and MultiDiGraph. If
  169. the input graph is an instance of one of these two classes, a
  170. NetworkXError is raised.
  171. NetworkXUnbounded
  172. If the graph has a path of infinite capacity, the value of a
  173. feasible flow on the graph is unbounded above and the function
  174. raises a NetworkXUnbounded.
  175. See also
  176. --------
  177. :meth:`maximum_flow`
  178. :meth:`minimum_cut`
  179. :meth:`minimum_cut_value`
  180. :meth:`edmonds_karp`
  181. :meth:`preflow_push`
  182. :meth:`shortest_augmenting_path`
  183. Notes
  184. -----
  185. The function used in the flow_func parameter has to return a residual
  186. network that follows NetworkX conventions:
  187. The residual network :samp:`R` from an input graph :samp:`G` has the
  188. same nodes as :samp:`G`. :samp:`R` is a DiGraph that contains a pair
  189. of edges :samp:`(u, v)` and :samp:`(v, u)` iff :samp:`(u, v)` is not a
  190. self-loop, and at least one of :samp:`(u, v)` and :samp:`(v, u)` exists
  191. in :samp:`G`.
  192. For each edge :samp:`(u, v)` in :samp:`R`, :samp:`R[u][v]['capacity']`
  193. is equal to the capacity of :samp:`(u, v)` in :samp:`G` if it exists
  194. in :samp:`G` or zero otherwise. If the capacity is infinite,
  195. :samp:`R[u][v]['capacity']` will have a high arbitrary finite value
  196. that does not affect the solution of the problem. This value is stored in
  197. :samp:`R.graph['inf']`. For each edge :samp:`(u, v)` in :samp:`R`,
  198. :samp:`R[u][v]['flow']` represents the flow function of :samp:`(u, v)` and
  199. satisfies :samp:`R[u][v]['flow'] == -R[v][u]['flow']`.
  200. The flow value, defined as the total flow into :samp:`t`, the sink, is
  201. stored in :samp:`R.graph['flow_value']`. Reachability to :samp:`t` using
  202. only edges :samp:`(u, v)` such that
  203. :samp:`R[u][v]['flow'] < R[u][v]['capacity']` induces a minimum
  204. :samp:`s`-:samp:`t` cut.
  205. Specific algorithms may store extra data in :samp:`R`.
  206. The function should supports an optional boolean parameter value_only. When
  207. True, it can optionally terminate the algorithm as soon as the maximum flow
  208. value and the minimum cut can be determined.
  209. Examples
  210. --------
  211. >>> G = nx.DiGraph()
  212. >>> G.add_edge("x", "a", capacity=3.0)
  213. >>> G.add_edge("x", "b", capacity=1.0)
  214. >>> G.add_edge("a", "c", capacity=3.0)
  215. >>> G.add_edge("b", "c", capacity=5.0)
  216. >>> G.add_edge("b", "d", capacity=4.0)
  217. >>> G.add_edge("d", "e", capacity=2.0)
  218. >>> G.add_edge("c", "y", capacity=2.0)
  219. >>> G.add_edge("e", "y", capacity=3.0)
  220. maximum_flow_value computes only the value of the
  221. maximum flow:
  222. >>> flow_value = nx.maximum_flow_value(G, "x", "y")
  223. >>> flow_value
  224. 3.0
  225. You can also use alternative algorithms for computing the
  226. maximum flow by using the flow_func parameter.
  227. >>> from networkx.algorithms.flow import shortest_augmenting_path
  228. >>> flow_value == nx.maximum_flow_value(
  229. ... G, "x", "y", flow_func=shortest_augmenting_path
  230. ... )
  231. True
  232. """
  233. if flow_func is None:
  234. if kwargs:
  235. raise nx.NetworkXError(
  236. "You have to explicitly set a flow_func if"
  237. " you need to pass parameters via kwargs."
  238. )
  239. flow_func = default_flow_func
  240. if not callable(flow_func):
  241. raise nx.NetworkXError("flow_func has to be callable.")
  242. R = flow_func(flowG, _s, _t, capacity=capacity, value_only=True, **kwargs)
  243. return R.graph["flow_value"]
  244. def minimum_cut(flowG, _s, _t, capacity="capacity", flow_func=None, **kwargs):
  245. """Compute the value and the node partition of a minimum (s, t)-cut.
  246. Use the max-flow min-cut theorem, i.e., the capacity of a minimum
  247. capacity cut is equal to the flow value of a maximum flow.
  248. Parameters
  249. ----------
  250. flowG : NetworkX graph
  251. Edges of the graph are expected to have an attribute called
  252. 'capacity'. If this attribute is not present, the edge is
  253. considered to have infinite capacity.
  254. _s : node
  255. Source node for the flow.
  256. _t : node
  257. Sink node for the flow.
  258. capacity : string
  259. Edges of the graph G are expected to have an attribute capacity
  260. that indicates how much flow the edge can support. If this
  261. attribute is not present, the edge is considered to have
  262. infinite capacity. Default value: 'capacity'.
  263. flow_func : function
  264. A function for computing the maximum flow among a pair of nodes
  265. in a capacitated graph. The function has to accept at least three
  266. parameters: a Graph or Digraph, a source node, and a target node.
  267. And return a residual network that follows NetworkX conventions
  268. (see Notes). If flow_func is None, the default maximum
  269. flow function (:meth:`preflow_push`) is used. See below for
  270. alternative algorithms. The choice of the default function may change
  271. from version to version and should not be relied on. Default value:
  272. None.
  273. kwargs : Any other keyword parameter is passed to the function that
  274. computes the maximum flow.
  275. Returns
  276. -------
  277. cut_value : integer, float
  278. Value of the minimum cut.
  279. partition : pair of node sets
  280. A partitioning of the nodes that defines a minimum cut.
  281. Raises
  282. ------
  283. NetworkXUnbounded
  284. If the graph has a path of infinite capacity, all cuts have
  285. infinite capacity and the function raises a NetworkXError.
  286. See also
  287. --------
  288. :meth:`maximum_flow`
  289. :meth:`maximum_flow_value`
  290. :meth:`minimum_cut_value`
  291. :meth:`edmonds_karp`
  292. :meth:`preflow_push`
  293. :meth:`shortest_augmenting_path`
  294. Notes
  295. -----
  296. The function used in the flow_func parameter has to return a residual
  297. network that follows NetworkX conventions:
  298. The residual network :samp:`R` from an input graph :samp:`G` has the
  299. same nodes as :samp:`G`. :samp:`R` is a DiGraph that contains a pair
  300. of edges :samp:`(u, v)` and :samp:`(v, u)` iff :samp:`(u, v)` is not a
  301. self-loop, and at least one of :samp:`(u, v)` and :samp:`(v, u)` exists
  302. in :samp:`G`.
  303. For each edge :samp:`(u, v)` in :samp:`R`, :samp:`R[u][v]['capacity']`
  304. is equal to the capacity of :samp:`(u, v)` in :samp:`G` if it exists
  305. in :samp:`G` or zero otherwise. If the capacity is infinite,
  306. :samp:`R[u][v]['capacity']` will have a high arbitrary finite value
  307. that does not affect the solution of the problem. This value is stored in
  308. :samp:`R.graph['inf']`. For each edge :samp:`(u, v)` in :samp:`R`,
  309. :samp:`R[u][v]['flow']` represents the flow function of :samp:`(u, v)` and
  310. satisfies :samp:`R[u][v]['flow'] == -R[v][u]['flow']`.
  311. The flow value, defined as the total flow into :samp:`t`, the sink, is
  312. stored in :samp:`R.graph['flow_value']`. Reachability to :samp:`t` using
  313. only edges :samp:`(u, v)` such that
  314. :samp:`R[u][v]['flow'] < R[u][v]['capacity']` induces a minimum
  315. :samp:`s`-:samp:`t` cut.
  316. Specific algorithms may store extra data in :samp:`R`.
  317. The function should supports an optional boolean parameter value_only. When
  318. True, it can optionally terminate the algorithm as soon as the maximum flow
  319. value and the minimum cut can be determined.
  320. Examples
  321. --------
  322. >>> G = nx.DiGraph()
  323. >>> G.add_edge("x", "a", capacity=3.0)
  324. >>> G.add_edge("x", "b", capacity=1.0)
  325. >>> G.add_edge("a", "c", capacity=3.0)
  326. >>> G.add_edge("b", "c", capacity=5.0)
  327. >>> G.add_edge("b", "d", capacity=4.0)
  328. >>> G.add_edge("d", "e", capacity=2.0)
  329. >>> G.add_edge("c", "y", capacity=2.0)
  330. >>> G.add_edge("e", "y", capacity=3.0)
  331. minimum_cut computes both the value of the
  332. minimum cut and the node partition:
  333. >>> cut_value, partition = nx.minimum_cut(G, "x", "y")
  334. >>> reachable, non_reachable = partition
  335. 'partition' here is a tuple with the two sets of nodes that define
  336. the minimum cut. You can compute the cut set of edges that induce
  337. the minimum cut as follows:
  338. >>> cutset = set()
  339. >>> for u, nbrs in ((n, G[n]) for n in reachable):
  340. ... cutset.update((u, v) for v in nbrs if v in non_reachable)
  341. >>> print(sorted(cutset))
  342. [('c', 'y'), ('x', 'b')]
  343. >>> cut_value == sum(G.edges[u, v]["capacity"] for (u, v) in cutset)
  344. True
  345. You can also use alternative algorithms for computing the
  346. minimum cut by using the flow_func parameter.
  347. >>> from networkx.algorithms.flow import shortest_augmenting_path
  348. >>> cut_value == nx.minimum_cut(G, "x", "y", flow_func=shortest_augmenting_path)[0]
  349. True
  350. """
  351. if flow_func is None:
  352. if kwargs:
  353. raise nx.NetworkXError(
  354. "You have to explicitly set a flow_func if"
  355. " you need to pass parameters via kwargs."
  356. )
  357. flow_func = default_flow_func
  358. if not callable(flow_func):
  359. raise nx.NetworkXError("flow_func has to be callable.")
  360. if kwargs.get("cutoff") is not None and flow_func is preflow_push:
  361. raise nx.NetworkXError("cutoff should not be specified.")
  362. R = flow_func(flowG, _s, _t, capacity=capacity, value_only=True, **kwargs)
  363. # Remove saturated edges from the residual network
  364. cutset = [(u, v, d) for u, v, d in R.edges(data=True) if d["flow"] == d["capacity"]]
  365. R.remove_edges_from(cutset)
  366. # Then, reachable and non reachable nodes from source in the
  367. # residual network form the node partition that defines
  368. # the minimum cut.
  369. non_reachable = set(dict(nx.shortest_path_length(R, target=_t)))
  370. partition = (set(flowG) - non_reachable, non_reachable)
  371. # Finally add again cutset edges to the residual network to make
  372. # sure that it is reusable.
  373. if cutset is not None:
  374. R.add_edges_from(cutset)
  375. return (R.graph["flow_value"], partition)
  376. def minimum_cut_value(flowG, _s, _t, capacity="capacity", flow_func=None, **kwargs):
  377. """Compute the value of a minimum (s, t)-cut.
  378. Use the max-flow min-cut theorem, i.e., the capacity of a minimum
  379. capacity cut is equal to the flow value of a maximum flow.
  380. Parameters
  381. ----------
  382. flowG : NetworkX graph
  383. Edges of the graph are expected to have an attribute called
  384. 'capacity'. If this attribute is not present, the edge is
  385. considered to have infinite capacity.
  386. _s : node
  387. Source node for the flow.
  388. _t : node
  389. Sink node for the flow.
  390. capacity : string
  391. Edges of the graph G are expected to have an attribute capacity
  392. that indicates how much flow the edge can support. If this
  393. attribute is not present, the edge is considered to have
  394. infinite capacity. Default value: 'capacity'.
  395. flow_func : function
  396. A function for computing the maximum flow among a pair of nodes
  397. in a capacitated graph. The function has to accept at least three
  398. parameters: a Graph or Digraph, a source node, and a target node.
  399. And return a residual network that follows NetworkX conventions
  400. (see Notes). If flow_func is None, the default maximum
  401. flow function (:meth:`preflow_push`) is used. See below for
  402. alternative algorithms. The choice of the default function may change
  403. from version to version and should not be relied on. Default value:
  404. None.
  405. kwargs : Any other keyword parameter is passed to the function that
  406. computes the maximum flow.
  407. Returns
  408. -------
  409. cut_value : integer, float
  410. Value of the minimum cut.
  411. Raises
  412. ------
  413. NetworkXUnbounded
  414. If the graph has a path of infinite capacity, all cuts have
  415. infinite capacity and the function raises a NetworkXError.
  416. See also
  417. --------
  418. :meth:`maximum_flow`
  419. :meth:`maximum_flow_value`
  420. :meth:`minimum_cut`
  421. :meth:`edmonds_karp`
  422. :meth:`preflow_push`
  423. :meth:`shortest_augmenting_path`
  424. Notes
  425. -----
  426. The function used in the flow_func parameter has to return a residual
  427. network that follows NetworkX conventions:
  428. The residual network :samp:`R` from an input graph :samp:`G` has the
  429. same nodes as :samp:`G`. :samp:`R` is a DiGraph that contains a pair
  430. of edges :samp:`(u, v)` and :samp:`(v, u)` iff :samp:`(u, v)` is not a
  431. self-loop, and at least one of :samp:`(u, v)` and :samp:`(v, u)` exists
  432. in :samp:`G`.
  433. For each edge :samp:`(u, v)` in :samp:`R`, :samp:`R[u][v]['capacity']`
  434. is equal to the capacity of :samp:`(u, v)` in :samp:`G` if it exists
  435. in :samp:`G` or zero otherwise. If the capacity is infinite,
  436. :samp:`R[u][v]['capacity']` will have a high arbitrary finite value
  437. that does not affect the solution of the problem. This value is stored in
  438. :samp:`R.graph['inf']`. For each edge :samp:`(u, v)` in :samp:`R`,
  439. :samp:`R[u][v]['flow']` represents the flow function of :samp:`(u, v)` and
  440. satisfies :samp:`R[u][v]['flow'] == -R[v][u]['flow']`.
  441. The flow value, defined as the total flow into :samp:`t`, the sink, is
  442. stored in :samp:`R.graph['flow_value']`. Reachability to :samp:`t` using
  443. only edges :samp:`(u, v)` such that
  444. :samp:`R[u][v]['flow'] < R[u][v]['capacity']` induces a minimum
  445. :samp:`s`-:samp:`t` cut.
  446. Specific algorithms may store extra data in :samp:`R`.
  447. The function should supports an optional boolean parameter value_only. When
  448. True, it can optionally terminate the algorithm as soon as the maximum flow
  449. value and the minimum cut can be determined.
  450. Examples
  451. --------
  452. >>> G = nx.DiGraph()
  453. >>> G.add_edge("x", "a", capacity=3.0)
  454. >>> G.add_edge("x", "b", capacity=1.0)
  455. >>> G.add_edge("a", "c", capacity=3.0)
  456. >>> G.add_edge("b", "c", capacity=5.0)
  457. >>> G.add_edge("b", "d", capacity=4.0)
  458. >>> G.add_edge("d", "e", capacity=2.0)
  459. >>> G.add_edge("c", "y", capacity=2.0)
  460. >>> G.add_edge("e", "y", capacity=3.0)
  461. minimum_cut_value computes only the value of the
  462. minimum cut:
  463. >>> cut_value = nx.minimum_cut_value(G, "x", "y")
  464. >>> cut_value
  465. 3.0
  466. You can also use alternative algorithms for computing the
  467. minimum cut by using the flow_func parameter.
  468. >>> from networkx.algorithms.flow import shortest_augmenting_path
  469. >>> cut_value == nx.minimum_cut_value(
  470. ... G, "x", "y", flow_func=shortest_augmenting_path
  471. ... )
  472. True
  473. """
  474. if flow_func is None:
  475. if kwargs:
  476. raise nx.NetworkXError(
  477. "You have to explicitly set a flow_func if"
  478. " you need to pass parameters via kwargs."
  479. )
  480. flow_func = default_flow_func
  481. if not callable(flow_func):
  482. raise nx.NetworkXError("flow_func has to be callable.")
  483. if kwargs.get("cutoff") is not None and flow_func is preflow_push:
  484. raise nx.NetworkXError("cutoff should not be specified.")
  485. R = flow_func(flowG, _s, _t, capacity=capacity, value_only=True, **kwargs)
  486. return R.graph["flow_value"]