Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.9/dist-packages/networkx/algorithms/flow/mincost.py: 56%
18 statements
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
« prev ^ index » next coverage.py v7.3.2, created at 2023-10-20 07:00 +0000
1"""
2Minimum cost flow algorithms on directed connected graphs.
3"""
5__all__ = ["min_cost_flow_cost", "min_cost_flow", "cost_of_flow", "max_flow_min_cost"]
7import networkx as nx
10@nx._dispatch(node_attrs="demand", edge_attrs={"capacity": float("inf"), "weight": 0})
11def min_cost_flow_cost(G, demand="demand", capacity="capacity", weight="weight"):
12 r"""Find the cost of a minimum cost flow satisfying all demands in digraph G.
14 G is a digraph with edge costs and capacities and in which nodes
15 have demand, i.e., they want to send or receive some amount of
16 flow. A negative demand means that the node wants to send flow, a
17 positive demand means that the node want to receive flow. A flow on
18 the digraph G satisfies all demand if the net flow into each node
19 is equal to the demand of that node.
21 Parameters
22 ----------
23 G : NetworkX graph
24 DiGraph on which a minimum cost flow satisfying all demands is
25 to be found.
27 demand : string
28 Nodes of the graph G are expected to have an attribute demand
29 that indicates how much flow a node wants to send (negative
30 demand) or receive (positive demand). Note that the sum of the
31 demands should be 0 otherwise the problem in not feasible. If
32 this attribute is not present, a node is considered to have 0
33 demand. Default value: 'demand'.
35 capacity : string
36 Edges of the graph G are expected to have an attribute capacity
37 that indicates how much flow the edge can support. If this
38 attribute is not present, the edge is considered to have
39 infinite capacity. Default value: 'capacity'.
41 weight : string
42 Edges of the graph G are expected to have an attribute weight
43 that indicates the cost incurred by sending one unit of flow on
44 that edge. If not present, the weight is considered to be 0.
45 Default value: 'weight'.
47 Returns
48 -------
49 flowCost : integer, float
50 Cost of a minimum cost flow satisfying all demands.
52 Raises
53 ------
54 NetworkXError
55 This exception is raised if the input graph is not directed or
56 not connected.
58 NetworkXUnfeasible
59 This exception is raised in the following situations:
61 * The sum of the demands is not zero. Then, there is no
62 flow satisfying all demands.
63 * There is no flow satisfying all demand.
65 NetworkXUnbounded
66 This exception is raised if the digraph G has a cycle of
67 negative cost and infinite capacity. Then, the cost of a flow
68 satisfying all demands is unbounded below.
70 See also
71 --------
72 cost_of_flow, max_flow_min_cost, min_cost_flow, network_simplex
74 Notes
75 -----
76 This algorithm is not guaranteed to work if edge weights or demands
77 are floating point numbers (overflows and roundoff errors can
78 cause problems). As a workaround you can use integer numbers by
79 multiplying the relevant edge attributes by a convenient
80 constant factor (eg 100).
82 Examples
83 --------
84 A simple example of a min cost flow problem.
86 >>> G = nx.DiGraph()
87 >>> G.add_node("a", demand=-5)
88 >>> G.add_node("d", demand=5)
89 >>> G.add_edge("a", "b", weight=3, capacity=4)
90 >>> G.add_edge("a", "c", weight=6, capacity=10)
91 >>> G.add_edge("b", "d", weight=1, capacity=9)
92 >>> G.add_edge("c", "d", weight=2, capacity=5)
93 >>> flowCost = nx.min_cost_flow_cost(G)
94 >>> flowCost
95 24
96 """
97 return nx.network_simplex(G, demand=demand, capacity=capacity, weight=weight)[0]
100@nx._dispatch(node_attrs="demand", edge_attrs={"capacity": float("inf"), "weight": 0})
101def min_cost_flow(G, demand="demand", capacity="capacity", weight="weight"):
102 r"""Returns a minimum cost flow satisfying all demands in digraph G.
104 G is a digraph with edge costs and capacities and in which nodes
105 have demand, i.e., they want to send or receive some amount of
106 flow. A negative demand means that the node wants to send flow, a
107 positive demand means that the node want to receive flow. A flow on
108 the digraph G satisfies all demand if the net flow into each node
109 is equal to the demand of that node.
111 Parameters
112 ----------
113 G : NetworkX graph
114 DiGraph on which a minimum cost flow satisfying all demands is
115 to be found.
117 demand : string
118 Nodes of the graph G are expected to have an attribute demand
119 that indicates how much flow a node wants to send (negative
120 demand) or receive (positive demand). Note that the sum of the
121 demands should be 0 otherwise the problem in not feasible. If
122 this attribute is not present, a node is considered to have 0
123 demand. Default value: 'demand'.
125 capacity : string
126 Edges of the graph G are expected to have an attribute capacity
127 that indicates how much flow the edge can support. If this
128 attribute is not present, the edge is considered to have
129 infinite capacity. Default value: 'capacity'.
131 weight : string
132 Edges of the graph G are expected to have an attribute weight
133 that indicates the cost incurred by sending one unit of flow on
134 that edge. If not present, the weight is considered to be 0.
135 Default value: 'weight'.
137 Returns
138 -------
139 flowDict : dictionary
140 Dictionary of dictionaries keyed by nodes such that
141 flowDict[u][v] is the flow edge (u, v).
143 Raises
144 ------
145 NetworkXError
146 This exception is raised if the input graph is not directed or
147 not connected.
149 NetworkXUnfeasible
150 This exception is raised in the following situations:
152 * The sum of the demands is not zero. Then, there is no
153 flow satisfying all demands.
154 * There is no flow satisfying all demand.
156 NetworkXUnbounded
157 This exception is raised if the digraph G has a cycle of
158 negative cost and infinite capacity. Then, the cost of a flow
159 satisfying all demands is unbounded below.
161 See also
162 --------
163 cost_of_flow, max_flow_min_cost, min_cost_flow_cost, network_simplex
165 Notes
166 -----
167 This algorithm is not guaranteed to work if edge weights or demands
168 are floating point numbers (overflows and roundoff errors can
169 cause problems). As a workaround you can use integer numbers by
170 multiplying the relevant edge attributes by a convenient
171 constant factor (eg 100).
173 Examples
174 --------
175 A simple example of a min cost flow problem.
177 >>> G = nx.DiGraph()
178 >>> G.add_node("a", demand=-5)
179 >>> G.add_node("d", demand=5)
180 >>> G.add_edge("a", "b", weight=3, capacity=4)
181 >>> G.add_edge("a", "c", weight=6, capacity=10)
182 >>> G.add_edge("b", "d", weight=1, capacity=9)
183 >>> G.add_edge("c", "d", weight=2, capacity=5)
184 >>> flowDict = nx.min_cost_flow(G)
185 """
186 return nx.network_simplex(G, demand=demand, capacity=capacity, weight=weight)[1]
189@nx._dispatch(edge_attrs={"weight": 0})
190def cost_of_flow(G, flowDict, weight="weight"):
191 """Compute the cost of the flow given by flowDict on graph G.
193 Note that this function does not check for the validity of the
194 flow flowDict. This function will fail if the graph G and the
195 flow don't have the same edge set.
197 Parameters
198 ----------
199 G : NetworkX graph
200 DiGraph on which a minimum cost flow satisfying all demands is
201 to be found.
203 weight : string
204 Edges of the graph G are expected to have an attribute weight
205 that indicates the cost incurred by sending one unit of flow on
206 that edge. If not present, the weight is considered to be 0.
207 Default value: 'weight'.
209 flowDict : dictionary
210 Dictionary of dictionaries keyed by nodes such that
211 flowDict[u][v] is the flow edge (u, v).
213 Returns
214 -------
215 cost : Integer, float
216 The total cost of the flow. This is given by the sum over all
217 edges of the product of the edge's flow and the edge's weight.
219 See also
220 --------
221 max_flow_min_cost, min_cost_flow, min_cost_flow_cost, network_simplex
223 Notes
224 -----
225 This algorithm is not guaranteed to work if edge weights or demands
226 are floating point numbers (overflows and roundoff errors can
227 cause problems). As a workaround you can use integer numbers by
228 multiplying the relevant edge attributes by a convenient
229 constant factor (eg 100).
230 """
231 return sum((flowDict[u][v] * d.get(weight, 0) for u, v, d in G.edges(data=True)))
234@nx._dispatch(edge_attrs={"capacity": float("inf"), "weight": 0})
235def max_flow_min_cost(G, s, t, capacity="capacity", weight="weight"):
236 """Returns a maximum (s, t)-flow of minimum cost.
238 G is a digraph with edge costs and capacities. There is a source
239 node s and a sink node t. This function finds a maximum flow from
240 s to t whose total cost is minimized.
242 Parameters
243 ----------
244 G : NetworkX graph
245 DiGraph on which a minimum cost flow satisfying all demands is
246 to be found.
248 s: node label
249 Source of the flow.
251 t: node label
252 Destination of the flow.
254 capacity: string
255 Edges of the graph G are expected to have an attribute capacity
256 that indicates how much flow the edge can support. If this
257 attribute is not present, the edge is considered to have
258 infinite capacity. Default value: 'capacity'.
260 weight: string
261 Edges of the graph G are expected to have an attribute weight
262 that indicates the cost incurred by sending one unit of flow on
263 that edge. If not present, the weight is considered to be 0.
264 Default value: 'weight'.
266 Returns
267 -------
268 flowDict: dictionary
269 Dictionary of dictionaries keyed by nodes such that
270 flowDict[u][v] is the flow edge (u, v).
272 Raises
273 ------
274 NetworkXError
275 This exception is raised if the input graph is not directed or
276 not connected.
278 NetworkXUnbounded
279 This exception is raised if there is an infinite capacity path
280 from s to t in G. In this case there is no maximum flow. This
281 exception is also raised if the digraph G has a cycle of
282 negative cost and infinite capacity. Then, the cost of a flow
283 is unbounded below.
285 See also
286 --------
287 cost_of_flow, min_cost_flow, min_cost_flow_cost, network_simplex
289 Notes
290 -----
291 This algorithm is not guaranteed to work if edge weights or demands
292 are floating point numbers (overflows and roundoff errors can
293 cause problems). As a workaround you can use integer numbers by
294 multiplying the relevant edge attributes by a convenient
295 constant factor (eg 100).
297 Examples
298 --------
299 >>> G = nx.DiGraph()
300 >>> G.add_edges_from(
301 ... [
302 ... (1, 2, {"capacity": 12, "weight": 4}),
303 ... (1, 3, {"capacity": 20, "weight": 6}),
304 ... (2, 3, {"capacity": 6, "weight": -3}),
305 ... (2, 6, {"capacity": 14, "weight": 1}),
306 ... (3, 4, {"weight": 9}),
307 ... (3, 5, {"capacity": 10, "weight": 5}),
308 ... (4, 2, {"capacity": 19, "weight": 13}),
309 ... (4, 5, {"capacity": 4, "weight": 0}),
310 ... (5, 7, {"capacity": 28, "weight": 2}),
311 ... (6, 5, {"capacity": 11, "weight": 1}),
312 ... (6, 7, {"weight": 8}),
313 ... (7, 4, {"capacity": 6, "weight": 6}),
314 ... ]
315 ... )
316 >>> mincostFlow = nx.max_flow_min_cost(G, 1, 7)
317 >>> mincost = nx.cost_of_flow(G, mincostFlow)
318 >>> mincost
319 373
320 >>> from networkx.algorithms.flow import maximum_flow
321 >>> maxFlow = maximum_flow(G, 1, 7)[1]
322 >>> nx.cost_of_flow(G, maxFlow) >= mincost
323 True
324 >>> mincostFlowValue = sum((mincostFlow[u][7] for u in G.predecessors(7))) - sum(
325 ... (mincostFlow[7][v] for v in G.successors(7))
326 ... )
327 >>> mincostFlowValue == nx.maximum_flow_value(G, 1, 7)
328 True
330 """
331 maxFlow = nx.maximum_flow_value(G, s, t, capacity=capacity)
332 H = nx.DiGraph(G)
333 H.add_node(s, demand=-maxFlow)
334 H.add_node(t, demand=maxFlow)
335 return min_cost_flow(H, capacity=capacity, weight=weight)