aboutsummaryrefslogtreecommitdiff
path: root/.venv/lib/python3.12/site-packages/networkx/algorithms/flow/mincost.py
diff options
context:
space:
mode:
authorS. Solomon Darnell2025-03-28 21:52:21 -0500
committerS. Solomon Darnell2025-03-28 21:52:21 -0500
commit4a52a71956a8d46fcb7294ac71734504bb09bcc2 (patch)
treeee3dc5af3b6313e921cd920906356f5d4febc4ed /.venv/lib/python3.12/site-packages/networkx/algorithms/flow/mincost.py
parentcc961e04ba734dd72309fb548a2f97d67d578813 (diff)
downloadgn-ai-master.tar.gz
two version of R2R are hereHEADmaster
Diffstat (limited to '.venv/lib/python3.12/site-packages/networkx/algorithms/flow/mincost.py')
-rw-r--r--.venv/lib/python3.12/site-packages/networkx/algorithms/flow/mincost.py356
1 files changed, 356 insertions, 0 deletions
diff --git a/.venv/lib/python3.12/site-packages/networkx/algorithms/flow/mincost.py b/.venv/lib/python3.12/site-packages/networkx/algorithms/flow/mincost.py
new file mode 100644
index 00000000..2f9390d7
--- /dev/null
+++ b/.venv/lib/python3.12/site-packages/networkx/algorithms/flow/mincost.py
@@ -0,0 +1,356 @@
+"""
+Minimum cost flow algorithms on directed connected graphs.
+"""
+
+__all__ = ["min_cost_flow_cost", "min_cost_flow", "cost_of_flow", "max_flow_min_cost"]
+
+import networkx as nx
+
+
+@nx._dispatchable(
+ node_attrs="demand", edge_attrs={"capacity": float("inf"), "weight": 0}
+)
+def min_cost_flow_cost(G, demand="demand", capacity="capacity", weight="weight"):
+ r"""Find the cost of a minimum cost flow satisfying all demands in digraph G.
+
+ G is a digraph with edge costs and capacities and in which nodes
+ have demand, i.e., they want to send or receive some amount of
+ flow. A negative demand means that the node wants to send flow, a
+ positive demand means that the node want to receive flow. A flow on
+ the digraph G satisfies all demand if the net flow into each node
+ is equal to the demand of that node.
+
+ Parameters
+ ----------
+ G : NetworkX graph
+ DiGraph on which a minimum cost flow satisfying all demands is
+ to be found.
+
+ demand : string
+ Nodes of the graph G are expected to have an attribute demand
+ that indicates how much flow a node wants to send (negative
+ demand) or receive (positive demand). Note that the sum of the
+ demands should be 0 otherwise the problem in not feasible. If
+ this attribute is not present, a node is considered to have 0
+ demand. Default value: 'demand'.
+
+ capacity : string
+ Edges of the graph G are expected to have an attribute capacity
+ that indicates how much flow the edge can support. If this
+ attribute is not present, the edge is considered to have
+ infinite capacity. Default value: 'capacity'.
+
+ weight : string
+ Edges of the graph G are expected to have an attribute weight
+ that indicates the cost incurred by sending one unit of flow on
+ that edge. If not present, the weight is considered to be 0.
+ Default value: 'weight'.
+
+ Returns
+ -------
+ flowCost : integer, float
+ Cost of a minimum cost flow satisfying all demands.
+
+ Raises
+ ------
+ NetworkXError
+ This exception is raised if the input graph is not directed or
+ not connected.
+
+ NetworkXUnfeasible
+ This exception is raised in the following situations:
+
+ * The sum of the demands is not zero. Then, there is no
+ flow satisfying all demands.
+ * There is no flow satisfying all demand.
+
+ NetworkXUnbounded
+ This exception is raised if the digraph G has a cycle of
+ negative cost and infinite capacity. Then, the cost of a flow
+ satisfying all demands is unbounded below.
+
+ See also
+ --------
+ cost_of_flow, max_flow_min_cost, min_cost_flow, network_simplex
+
+ Notes
+ -----
+ This algorithm is not guaranteed to work if edge weights or demands
+ are floating point numbers (overflows and roundoff errors can
+ cause problems). As a workaround you can use integer numbers by
+ multiplying the relevant edge attributes by a convenient
+ constant factor (eg 100).
+
+ Examples
+ --------
+ A simple example of a min cost flow problem.
+
+ >>> G = nx.DiGraph()
+ >>> G.add_node("a", demand=-5)
+ >>> G.add_node("d", demand=5)
+ >>> G.add_edge("a", "b", weight=3, capacity=4)
+ >>> G.add_edge("a", "c", weight=6, capacity=10)
+ >>> G.add_edge("b", "d", weight=1, capacity=9)
+ >>> G.add_edge("c", "d", weight=2, capacity=5)
+ >>> flowCost = nx.min_cost_flow_cost(G)
+ >>> flowCost
+ 24
+ """
+ return nx.network_simplex(G, demand=demand, capacity=capacity, weight=weight)[0]
+
+
+@nx._dispatchable(
+ node_attrs="demand", edge_attrs={"capacity": float("inf"), "weight": 0}
+)
+def min_cost_flow(G, demand="demand", capacity="capacity", weight="weight"):
+ r"""Returns a minimum cost flow satisfying all demands in digraph G.
+
+ G is a digraph with edge costs and capacities and in which nodes
+ have demand, i.e., they want to send or receive some amount of
+ flow. A negative demand means that the node wants to send flow, a
+ positive demand means that the node want to receive flow. A flow on
+ the digraph G satisfies all demand if the net flow into each node
+ is equal to the demand of that node.
+
+ Parameters
+ ----------
+ G : NetworkX graph
+ DiGraph on which a minimum cost flow satisfying all demands is
+ to be found.
+
+ demand : string
+ Nodes of the graph G are expected to have an attribute demand
+ that indicates how much flow a node wants to send (negative
+ demand) or receive (positive demand). Note that the sum of the
+ demands should be 0 otherwise the problem in not feasible. If
+ this attribute is not present, a node is considered to have 0
+ demand. Default value: 'demand'.
+
+ capacity : string
+ Edges of the graph G are expected to have an attribute capacity
+ that indicates how much flow the edge can support. If this
+ attribute is not present, the edge is considered to have
+ infinite capacity. Default value: 'capacity'.
+
+ weight : string
+ Edges of the graph G are expected to have an attribute weight
+ that indicates the cost incurred by sending one unit of flow on
+ that edge. If not present, the weight is considered to be 0.
+ Default value: 'weight'.
+
+ Returns
+ -------
+ flowDict : dictionary
+ Dictionary of dictionaries keyed by nodes such that
+ flowDict[u][v] is the flow edge (u, v).
+
+ Raises
+ ------
+ NetworkXError
+ This exception is raised if the input graph is not directed or
+ not connected.
+
+ NetworkXUnfeasible
+ This exception is raised in the following situations:
+
+ * The sum of the demands is not zero. Then, there is no
+ flow satisfying all demands.
+ * There is no flow satisfying all demand.
+
+ NetworkXUnbounded
+ This exception is raised if the digraph G has a cycle of
+ negative cost and infinite capacity. Then, the cost of a flow
+ satisfying all demands is unbounded below.
+
+ See also
+ --------
+ cost_of_flow, max_flow_min_cost, min_cost_flow_cost, network_simplex
+
+ Notes
+ -----
+ This algorithm is not guaranteed to work if edge weights or demands
+ are floating point numbers (overflows and roundoff errors can
+ cause problems). As a workaround you can use integer numbers by
+ multiplying the relevant edge attributes by a convenient
+ constant factor (eg 100).
+
+ Examples
+ --------
+ A simple example of a min cost flow problem.
+
+ >>> G = nx.DiGraph()
+ >>> G.add_node("a", demand=-5)
+ >>> G.add_node("d", demand=5)
+ >>> G.add_edge("a", "b", weight=3, capacity=4)
+ >>> G.add_edge("a", "c", weight=6, capacity=10)
+ >>> G.add_edge("b", "d", weight=1, capacity=9)
+ >>> G.add_edge("c", "d", weight=2, capacity=5)
+ >>> flowDict = nx.min_cost_flow(G)
+ >>> flowDict
+ {'a': {'b': 4, 'c': 1}, 'd': {}, 'b': {'d': 4}, 'c': {'d': 1}}
+ """
+ return nx.network_simplex(G, demand=demand, capacity=capacity, weight=weight)[1]
+
+
+@nx._dispatchable(edge_attrs={"weight": 0})
+def cost_of_flow(G, flowDict, weight="weight"):
+ """Compute the cost of the flow given by flowDict on graph G.
+
+ Note that this function does not check for the validity of the
+ flow flowDict. This function will fail if the graph G and the
+ flow don't have the same edge set.
+
+ Parameters
+ ----------
+ G : NetworkX graph
+ DiGraph on which a minimum cost flow satisfying all demands is
+ to be found.
+
+ weight : string
+ Edges of the graph G are expected to have an attribute weight
+ that indicates the cost incurred by sending one unit of flow on
+ that edge. If not present, the weight is considered to be 0.
+ Default value: 'weight'.
+
+ flowDict : dictionary
+ Dictionary of dictionaries keyed by nodes such that
+ flowDict[u][v] is the flow edge (u, v).
+
+ Returns
+ -------
+ cost : Integer, float
+ The total cost of the flow. This is given by the sum over all
+ edges of the product of the edge's flow and the edge's weight.
+
+ See also
+ --------
+ max_flow_min_cost, min_cost_flow, min_cost_flow_cost, network_simplex
+
+ Notes
+ -----
+ This algorithm is not guaranteed to work if edge weights or demands
+ are floating point numbers (overflows and roundoff errors can
+ cause problems). As a workaround you can use integer numbers by
+ multiplying the relevant edge attributes by a convenient
+ constant factor (eg 100).
+
+ Examples
+ --------
+ >>> G = nx.DiGraph()
+ >>> G.add_node("a", demand=-5)
+ >>> G.add_node("d", demand=5)
+ >>> G.add_edge("a", "b", weight=3, capacity=4)
+ >>> G.add_edge("a", "c", weight=6, capacity=10)
+ >>> G.add_edge("b", "d", weight=1, capacity=9)
+ >>> G.add_edge("c", "d", weight=2, capacity=5)
+ >>> flowDict = nx.min_cost_flow(G)
+ >>> flowDict
+ {'a': {'b': 4, 'c': 1}, 'd': {}, 'b': {'d': 4}, 'c': {'d': 1}}
+ >>> nx.cost_of_flow(G, flowDict)
+ 24
+ """
+ return sum((flowDict[u][v] * d.get(weight, 0) for u, v, d in G.edges(data=True)))
+
+
+@nx._dispatchable(edge_attrs={"capacity": float("inf"), "weight": 0})
+def max_flow_min_cost(G, s, t, capacity="capacity", weight="weight"):
+ """Returns a maximum (s, t)-flow of minimum cost.
+
+ G is a digraph with edge costs and capacities. There is a source
+ node s and a sink node t. This function finds a maximum flow from
+ s to t whose total cost is minimized.
+
+ Parameters
+ ----------
+ G : NetworkX graph
+ DiGraph on which a minimum cost flow satisfying all demands is
+ to be found.
+
+ s: node label
+ Source of the flow.
+
+ t: node label
+ Destination of the flow.
+
+ capacity: string
+ Edges of the graph G are expected to have an attribute capacity
+ that indicates how much flow the edge can support. If this
+ attribute is not present, the edge is considered to have
+ infinite capacity. Default value: 'capacity'.
+
+ weight: string
+ Edges of the graph G are expected to have an attribute weight
+ that indicates the cost incurred by sending one unit of flow on
+ that edge. If not present, the weight is considered to be 0.
+ Default value: 'weight'.
+
+ Returns
+ -------
+ flowDict: dictionary
+ Dictionary of dictionaries keyed by nodes such that
+ flowDict[u][v] is the flow edge (u, v).
+
+ Raises
+ ------
+ NetworkXError
+ This exception is raised if the input graph is not directed or
+ not connected.
+
+ NetworkXUnbounded
+ This exception is raised if there is an infinite capacity path
+ from s to t in G. In this case there is no maximum flow. This
+ exception is also raised if the digraph G has a cycle of
+ negative cost and infinite capacity. Then, the cost of a flow
+ is unbounded below.
+
+ See also
+ --------
+ cost_of_flow, min_cost_flow, min_cost_flow_cost, network_simplex
+
+ Notes
+ -----
+ This algorithm is not guaranteed to work if edge weights or demands
+ are floating point numbers (overflows and roundoff errors can
+ cause problems). As a workaround you can use integer numbers by
+ multiplying the relevant edge attributes by a convenient
+ constant factor (eg 100).
+
+ Examples
+ --------
+ >>> G = nx.DiGraph()
+ >>> G.add_edges_from(
+ ... [
+ ... (1, 2, {"capacity": 12, "weight": 4}),
+ ... (1, 3, {"capacity": 20, "weight": 6}),
+ ... (2, 3, {"capacity": 6, "weight": -3}),
+ ... (2, 6, {"capacity": 14, "weight": 1}),
+ ... (3, 4, {"weight": 9}),
+ ... (3, 5, {"capacity": 10, "weight": 5}),
+ ... (4, 2, {"capacity": 19, "weight": 13}),
+ ... (4, 5, {"capacity": 4, "weight": 0}),
+ ... (5, 7, {"capacity": 28, "weight": 2}),
+ ... (6, 5, {"capacity": 11, "weight": 1}),
+ ... (6, 7, {"weight": 8}),
+ ... (7, 4, {"capacity": 6, "weight": 6}),
+ ... ]
+ ... )
+ >>> mincostFlow = nx.max_flow_min_cost(G, 1, 7)
+ >>> mincost = nx.cost_of_flow(G, mincostFlow)
+ >>> mincost
+ 373
+ >>> from networkx.algorithms.flow import maximum_flow
+ >>> maxFlow = maximum_flow(G, 1, 7)[1]
+ >>> nx.cost_of_flow(G, maxFlow) >= mincost
+ True
+ >>> mincostFlowValue = sum((mincostFlow[u][7] for u in G.predecessors(7))) - sum(
+ ... (mincostFlow[7][v] for v in G.successors(7))
+ ... )
+ >>> mincostFlowValue == nx.maximum_flow_value(G, 1, 7)
+ True
+
+ """
+ maxFlow = nx.maximum_flow_value(G, s, t, capacity=capacity)
+ H = nx.DiGraph(G)
+ H.add_node(s, demand=-maxFlow)
+ H.add_node(t, demand=maxFlow)
+ return min_cost_flow(H, capacity=capacity, weight=weight)