summaryrefslogtreecommitdiff
path: root/networkx/algorithms/flow
diff options
context:
space:
mode:
authorDan Schult <dschult@colgate.edu>2017-08-12 17:20:15 -0600
committerGitHub <noreply@github.com>2017-08-12 17:20:15 -0600
commit2c6740efbebf56fc28686bc01c49f541f307d353 (patch)
tree5c6db5caf25b2dddfa4e0d3df4e35e1bd67d859e /networkx/algorithms/flow
parentd72aca7a92c7de6d854e50ec4dc7235842780490 (diff)
downloadnetworkx-2c6740efbebf56fc28686bc01c49f541f307d353.tar.gz
Simplify base classes. (#2604)
* move selfloop methods out of graph classes into function.py * replace G.node with G.nodes. fix Pickle of views * Replace G.edge with G.edges * Add a few lines of docs for release realted to this PR.
Diffstat (limited to 'networkx/algorithms/flow')
-rw-r--r--networkx/algorithms/flow/capacityscaling.py38
-rw-r--r--networkx/algorithms/flow/edmondskarp.py2
-rw-r--r--networkx/algorithms/flow/maxflow.py2
-rw-r--r--networkx/algorithms/flow/networksimplex.py12
-rw-r--r--networkx/algorithms/flow/preflowpush.py52
-rw-r--r--networkx/algorithms/flow/shortestaugmentingpath.py20
-rw-r--r--networkx/algorithms/flow/tests/test_mincost.py8
7 files changed, 67 insertions, 67 deletions
diff --git a/networkx/algorithms/flow/capacityscaling.py b/networkx/algorithms/flow/capacityscaling.py
index 1a425075..b184721b 100644
--- a/networkx/algorithms/flow/capacityscaling.py
+++ b/networkx/algorithms/flow/capacityscaling.py
@@ -49,16 +49,16 @@ def _detect_unboundedness(R):
def _build_residual_network(G, demand, capacity, weight):
"""Build a residual network and initialize a zero flow.
"""
- if sum(G.node[u].get(demand, 0) for u in G) != 0:
+ if sum(G.nodes[u].get(demand, 0) for u in G) != 0:
raise nx.NetworkXUnfeasible("Sum of the demands should be 0.")
R = nx.MultiDiGraph()
- R.add_nodes_from((u, {'excess': -G.node[u].get(demand, 0),
+ R.add_nodes_from((u, {'excess': -G.nodes[u].get(demand, 0),
'potential': 0}) for u in G)
inf = float('inf')
# Detect selfloops with infinite capacities and negative weights.
- for u, v, e in G.selfloop_edges(data=True):
+ for u, v, e in nx.selfloop_edges(G, data=True):
if e.get(weight, 0) < 0 and e.get(capacity, inf) == inf:
raise nx.NetworkXUnbounded(
'Negative cost cycle of infinite capacity found. '
@@ -77,7 +77,7 @@ def _build_residual_network(G, demand, capacity, weight):
# zero. This allows the infinite-capacity edges to be distinguished for
# unboundedness detection and directly participate in residual capacity
# calculation.
- inf = max(sum(abs(R.node[u]['excess']) for u in R),
+ inf = max(sum(abs(R.nodes[u]['excess']) for u in R),
2 * sum(e[capacity] for u, v, k, e in edge_list
if capacity in e and e[capacity] != inf)) or 1
for u, v, k, e in edge_list:
@@ -265,7 +265,7 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
flow_cost = sum(
0 if e.get(capacity, inf) <= 0 or e.get(weight, 0) >= 0
else e[capacity] * e[weight]
- for u, v, e in G.selfloop_edges(data=True))
+ for u, v, e in nx.selfloop_edges(G,data=True))
# Determine the maxmimum edge capacity.
wmax = max(chain([-inf],
@@ -274,7 +274,7 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
# Residual network has no edges.
return flow_cost, _build_flow_dict(G, R, capacity, weight)
- R_node = R.node
+ R_nodes = R.nodes
R_succ = R.succ
delta = 2 ** int(log(wmax, 2))
@@ -282,17 +282,17 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
# Saturate Δ-residual edges with negative reduced costs to achieve
# Δ-optimality.
for u in R:
- p_u = R_node[u]['potential']
+ p_u = R_nodes[u]['potential']
for v, es in R_succ[u].items():
for k, e in es.items():
flow = e['capacity'] - e['flow']
- if e['weight'] - p_u + R_node[v]['potential'] < 0:
+ if e['weight'] - p_u + R_nodes[v]['potential'] < 0:
flow = e['capacity'] - e['flow']
if flow >= delta:
e['flow'] += flow
R_succ[v][u][(k[0], not k[1])]['flow'] -= flow
- R_node[u]['excess'] -= flow
- R_node[v]['excess'] += flow
+ R_nodes[u]['excess'] -= flow
+ R_nodes[v]['excess'] += flow
# Determine the Δ-active nodes.
S = set()
T = set()
@@ -301,7 +301,7 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
T_add = T.add
T_remove = T.remove
for u in R:
- excess = R_node[u]['excess']
+ excess = R_nodes[u]['excess']
if excess >= delta:
S_add(u)
elif excess <= -delta:
@@ -326,7 +326,7 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
# Path found.
t = u
break
- p_u = R_node[u]['potential']
+ p_u = R_nodes[u]['potential']
for v, es in R_succ[u].items():
if v in d:
continue
@@ -342,7 +342,7 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
if wmin == inf:
continue
# Update the distance label of v.
- d_v = d_u + wmin - p_u + R_node[v]['potential']
+ d_v = d_u + wmin - p_u + R_nodes[v]['potential']
if h_insert(v, d_v):
pred[v] = (u, kmin, emin)
if t is not None:
@@ -353,22 +353,22 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
e['flow'] += delta
R_succ[v][u][(k[0], not k[1])]['flow'] -= delta
# Account node excess and deficit.
- R_node[s]['excess'] -= delta
- R_node[t]['excess'] += delta
- if R_node[s]['excess'] < delta:
+ R_nodes[s]['excess'] -= delta
+ R_nodes[t]['excess'] += delta
+ if R_nodes[s]['excess'] < delta:
S_remove(s)
- if R_node[t]['excess'] > -delta:
+ if R_nodes[t]['excess'] > -delta:
T_remove(t)
# Update node potentials.
d_t = d[t]
for u, d_u in d.items():
- R_node[u]['potential'] -= d_u - d_t
+ R_nodes[u]['potential'] -= d_u - d_t
else:
# Path not found.
S_remove(s)
delta //= 2
- if any(R.node[u]['excess'] != 0 for u in R):
+ if any(R.nodes[u]['excess'] != 0 for u in R):
raise nx.NetworkXUnfeasible('No flow satisfying all demands.')
# Calculate the flow cost.
diff --git a/networkx/algorithms/flow/edmondskarp.py b/networkx/algorithms/flow/edmondskarp.py
index d1bffc42..81ec7e66 100644
--- a/networkx/algorithms/flow/edmondskarp.py
+++ b/networkx/algorithms/flow/edmondskarp.py
@@ -17,7 +17,7 @@ __all__ = ['edmonds_karp']
def edmonds_karp_core(R, s, t, cutoff):
"""Implementation of the Edmonds-Karp algorithm.
"""
- R_node = R.node
+ R_nodes = R.nodes
R_pred = R.pred
R_succ = R.succ
diff --git a/networkx/algorithms/flow/maxflow.py b/networkx/algorithms/flow/maxflow.py
index 41ce4c52..3909c00a 100644
--- a/networkx/algorithms/flow/maxflow.py
+++ b/networkx/algorithms/flow/maxflow.py
@@ -430,7 +430,7 @@ def minimum_cut(G, s, t, capacity='capacity', flow_func=None, **kwargs):
... cutset.update((u, v) for v in nbrs if v in non_reachable)
>>> print(sorted(cutset))
[('c', 'y'), ('x', 'b')]
- >>> cut_value == sum(G.edge[u, v]['capacity'] for (u, v) in cutset)
+ >>> cut_value == sum(G.edges[u, v]['capacity'] for (u, v) in cutset)
True
You can also use alternative algorithms for computing the
diff --git a/networkx/algorithms/flow/networksimplex.py b/networkx/algorithms/flow/networksimplex.py
index 5a346afd..9bfb06b0 100644
--- a/networkx/algorithms/flow/networksimplex.py
+++ b/networkx/algorithms/flow/networksimplex.py
@@ -192,7 +192,7 @@ def network_simplex(G, demand='demand', capacity='capacity', weight='weight'):
N = list(G) # nodes
I = {u: i for i, u in enumerate(N)} # node indices
- D = [G.node[u].get(demand, 0) for u in N] # node demands
+ D = [G.nodes[u].get(demand, 0) for u in N] # node demands
inf = float('inf')
for p, b in zip(N, D):
@@ -227,9 +227,9 @@ def network_simplex(G, demand='demand', capacity='capacity', weight='weight'):
if abs(c) == inf:
raise nx.NetworkXError('edge %r has infinite weight' % (e,))
if not multigraph:
- edges = G.selfloop_edges(data=True)
+ edges = nx.selfloop_edges(G, data=True)
else:
- edges = G.selfloop_edges(data=True, keys=True)
+ edges = nx.selfloop_edges(G, data=True, keys=True)
for e in edges:
if abs(e[-1].get(weight, 0)) == inf:
raise nx.NetworkXError('edge %r has infinite weight' % (e[:-1],))
@@ -244,9 +244,9 @@ def network_simplex(G, demand='demand', capacity='capacity', weight='weight'):
if u < 0:
raise nx.NetworkXUnfeasible('edge %r has negative capacity' % (e,))
if not multigraph:
- edges = G.selfloop_edges(data=True)
+ edges = nx.selfloop_edges(G, data=True)
else:
- edges = G.selfloop_edges(data=True, keys=True)
+ edges = nx.selfloop_edges(G, data=True, keys=True)
for e in edges:
if e[-1].get(capacity, inf) < 0:
raise nx.NetworkXUnfeasible(
@@ -547,7 +547,7 @@ def network_simplex(G, demand='demand', capacity='capacity', weight='weight'):
if (any(x[i] * 2 >= faux_inf for i in range(e)) or
any(e[-1].get(capacity, inf) == inf and e[-1].get(weight, 0) < 0
- for e in G.selfloop_edges(data=True))):
+ for e in nx.selfloop_edges(G, data=True))):
raise nx.NetworkXUnbounded(
'negative cycle with infinite capacity found')
diff --git a/networkx/algorithms/flow/preflowpush.py b/networkx/algorithms/flow/preflowpush.py
index 6bb3e4a0..f9904cc3 100644
--- a/networkx/algorithms/flow/preflowpush.py
+++ b/networkx/algorithms/flow/preflowpush.py
@@ -45,13 +45,13 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
detect_unboundedness(R, s, t)
- R_node = R.node
+ R_nodes = R.nodes
R_pred = R.pred
R_succ = R.succ
# Initialize/reset the residual network.
for u in R:
- R_node[u]['excess'] = 0
+ R_nodes[u]['excess'] = 0
for e in R_succ[u].values():
e['flow'] = 0
@@ -89,16 +89,16 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
# Initialize heights and 'current edge' data structures of the nodes.
for u in R:
- R_node[u]['height'] = heights[u] if u in heights else n + 1
- R_node[u]['curr_edge'] = CurrentEdge(R_succ[u])
+ R_nodes[u]['height'] = heights[u] if u in heights else n + 1
+ R_nodes[u]['curr_edge'] = CurrentEdge(R_succ[u])
def push(u, v, flow):
"""Push flow units of flow from u to v.
"""
R_succ[u][v]['flow'] += flow
R_succ[v][u]['flow'] -= flow
- R_node[u]['excess'] -= flow
- R_node[v]['excess'] += flow
+ R_nodes[u]['excess'] -= flow
+ R_nodes[v]['excess'] += flow
# The maximum flow must be nonzero now. Initialize the preflow by
# saturating all edges emanating from s.
@@ -111,8 +111,8 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
levels = [Level() for i in range(2 * n)]
for u in R:
if u != s and u != t:
- level = levels[R_node[u]['height']]
- if R_node[u]['excess'] > 0:
+ level = levels[R_nodes[u]['height']]
+ if R_nodes[u]['excess'] > 0:
level.active.add(u)
else:
level.inactive.add(u)
@@ -121,7 +121,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
"""Move a node from the inactive set to the active set of its level.
"""
if v != s and v != t:
- level = levels[R_node[v]['height']]
+ level = levels[R_nodes[v]['height']]
if v in level.inactive:
level.inactive.remove(v)
level.active.add(v)
@@ -130,7 +130,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
"""Relabel a node to create an admissible edge.
"""
grt.add_work(len(R_succ[u]))
- return min(R_node[v]['height'] for v, attr in R_succ[u].items()
+ return min(R_nodes[v]['height'] for v, attr in R_succ[u].items()
if attr['flow'] < attr['capacity']) + 1
def discharge(u, is_phase1):
@@ -138,21 +138,21 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
below), its height reaches at least n. The node is known to have the
largest height among active nodes.
"""
- height = R_node[u]['height']
- curr_edge = R_node[u]['curr_edge']
+ height = R_nodes[u]['height']
+ curr_edge = R_nodes[u]['curr_edge']
# next_height represents the next height to examine after discharging
# the current node. During phase 1, it is capped to below n.
next_height = height
levels[height].active.remove(u)
while True:
v, attr = curr_edge.get()
- if (height == R_node[v]['height'] + 1 and
+ if (height == R_nodes[v]['height'] + 1 and
attr['flow'] < attr['capacity']):
- flow = min(R_node[u]['excess'],
+ flow = min(R_nodes[u]['excess'],
attr['capacity'] - attr['flow'])
push(u, v, flow)
activate(v)
- if R_node[u]['excess'] == 0:
+ if R_nodes[u]['excess'] == 0:
# The node has become inactive.
levels[height].inactive.add(u)
break
@@ -173,7 +173,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
# structure is not rewound. Use height instead of (height - 1)
# in case other active nodes at the same level are missed.
next_height = height
- R_node[u]['height'] = height
+ R_nodes[u]['height'] = height
return next_height
def gap_heuristic(height):
@@ -182,9 +182,9 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
# Move all nodes at levels (height + 1) to max_height to level n + 1.
for level in islice(levels, height + 1, max_height + 1):
for u in level.active:
- R_node[u]['height'] = n + 1
+ R_nodes[u]['height'] = n + 1
for u in level.inactive:
- R_node[u]['height'] = n + 1
+ R_nodes[u]['height'] = n + 1
levels[n + 1].active.update(level.active)
level.active.clear()
levels[n + 1].inactive.update(level.inactive)
@@ -203,7 +203,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
# Also mark nodes from which t is unreachable for relabeling. This
# serves the same purpose as the gap heuristic.
for u in R:
- if u not in heights and R_node[u]['height'] < n:
+ if u not in heights and R_nodes[u]['height'] < n:
heights[u] = n + 1
else:
# Shift the computed heights because the height of s is n.
@@ -212,7 +212,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
max_height += n
del heights[src]
for u, new_height in heights.items():
- old_height = R_node[u]['height']
+ old_height = R_nodes[u]['height']
if new_height != old_height:
if u in levels[old_height].active:
levels[old_height].active.remove(u)
@@ -220,7 +220,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
else:
levels[old_height].inactive.remove(u)
levels[new_height].inactive.add(u)
- R_node[u]['height'] = new_height
+ R_nodes[u]['height'] = new_height
return max_height
# Phase 1: Find the maximum preflow by pushing as much flow as possible to
@@ -263,7 +263,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
# A maximum preflow has been found. The excess at t is the maximum flow
# value.
if value_only:
- R.graph['flow_value'] = R_node[t]['excess']
+ R.graph['flow_value'] = R_nodes[t]['excess']
return R
# Phase 2: Convert the maximum preflow into a maximum flow by returning the
@@ -290,7 +290,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
height = global_relabel(False)
grt.clear_work()
- R.graph['flow_value'] = R_node[t]['excess']
+ R.graph['flow_value'] = R_nodes[t]['excess']
return R
@@ -371,7 +371,7 @@ def preflow_push(G, s, t, capacity='capacity', residual=None,
of edges :samp:`(u, v)` and :samp:`(v, u)` iff :samp:`(u, v)` is not a
self-loop, and at least one of :samp:`(u, v)` and :samp:`(v, u)` exists
in :samp:`G`. For each node :samp:`u` in :samp:`R`,
- :samp:`R.node[u]['excess']` represents the difference between flow into
+ :samp:`R.nodes[u]['excess']` represents the difference between flow into
:samp:`u` and flow out of :samp:`u`.
For each edge :samp:`(u, v)` in :samp:`R`, :samp:`R[u][v]['capacity']`
@@ -413,14 +413,14 @@ def preflow_push(G, s, t, capacity='capacity', residual=None,
True
>>> # preflow_push also stores the maximum flow value
>>> # in the excess attribute of the sink node t
- >>> flow_value == R.node['y']['excess']
+ >>> flow_value == R.nodes['y']['excess']
True
>>> # For some problems, you might only want to compute a
>>> # maximum preflow.
>>> R = preflow_push(G, 'x', 'y', value_only=True)
>>> flow_value == R.graph['flow_value']
True
- >>> flow_value == R.node['y']['excess']
+ >>> flow_value == R.nodes['y']['excess']
True
"""
diff --git a/networkx/algorithms/flow/shortestaugmentingpath.py b/networkx/algorithms/flow/shortestaugmentingpath.py
index 938ca834..f2440d5e 100644
--- a/networkx/algorithms/flow/shortestaugmentingpath.py
+++ b/networkx/algorithms/flow/shortestaugmentingpath.py
@@ -32,7 +32,7 @@ def shortest_augmenting_path_impl(G, s, t, capacity, residual, two_phase,
else:
R = residual
- R_node = R.node
+ R_nodes = R.nodes
R_pred = R.pred
R_succ = R.succ
@@ -63,13 +63,13 @@ def shortest_augmenting_path_impl(G, s, t, capacity, residual, two_phase,
# Initialize heights and 'current edge' data structures of the nodes.
for u in R:
- R_node[u]['height'] = heights[u] if u in heights else n
- R_node[u]['curr_edge'] = CurrentEdge(R_succ[u])
+ R_nodes[u]['height'] = heights[u] if u in heights else n
+ R_nodes[u]['curr_edge'] = CurrentEdge(R_succ[u])
# Initialize counts of nodes in each level.
counts = [0] * (2 * n - 1)
for u in R:
- counts[R_node[u]['height']] += 1
+ counts[R_nodes[u]['height']] += 1
inf = R.graph['inf']
def augment(path):
@@ -101,7 +101,7 @@ def shortest_augmenting_path_impl(G, s, t, capacity, residual, two_phase,
height = n - 1
for v, attr in R_succ[u].items():
if attr['flow'] < attr['capacity']:
- height = min(height, R_node[v]['height'])
+ height = min(height, R_nodes[v]['height'])
return height + 1
if cutoff is None:
@@ -113,14 +113,14 @@ def shortest_augmenting_path_impl(G, s, t, capacity, residual, two_phase,
path = [s]
u = s
d = n if not two_phase else int(min(m ** 0.5, 2 * n ** (2. / 3)))
- done = R_node[s]['height'] >= d
+ done = R_nodes[s]['height'] >= d
while not done:
- height = R_node[u]['height']
- curr_edge = R_node[u]['curr_edge']
+ height = R_nodes[u]['height']
+ curr_edge = R_nodes[u]['curr_edge']
# Depth-first search for the next node on the path to t.
while True:
v, attr = curr_edge.get()
- if (height == R_node[v]['height'] + 1 and
+ if (height == R_nodes[v]['height'] + 1 and
attr['flow'] < attr['capacity']):
# Advance to the next node following an admissible edge.
path.append(v)
@@ -148,7 +148,7 @@ def shortest_augmenting_path_impl(G, s, t, capacity, residual, two_phase,
done = True
break
counts[height] += 1
- R_node[u]['height'] = height
+ R_nodes[u]['height'] = height
if u != s:
# After relabeling, the last edge on the path is no longer
# admissible. Retreat one step to look for an alternative.
diff --git a/networkx/algorithms/flow/tests/test_mincost.py b/networkx/algorithms/flow/tests/test_mincost.py
index fae01faf..7ed3de76 100644
--- a/networkx/algorithms/flow/tests/test_mincost.py
+++ b/networkx/algorithms/flow/tests/test_mincost.py
@@ -270,9 +270,9 @@ class TestMinCostFlow:
(5, 3, {'capacity': 2, 'weight': 1}),
(5, 4, {'capacity': 0, 'weight': 1}),
(3, 4, {'capacity': 2, 'weight': 1})])
- G.node[1]['demand'] = -1
- G.node[2]['demand'] = -1
- G.node[4]['demand'] = 2
+ G.nodes[1]['demand'] = -1
+ G.nodes[2]['demand'] = -1
+ G.nodes[4]['demand'] = 2
flowCost, H = nx.network_simplex(G)
soln = {1: {2: 0, 5: 1},
@@ -428,7 +428,7 @@ class TestMinCostFlow:
G.add_node(0, demand=float('inf'))
assert_raises(nx.NetworkXError, nx.network_simplex, G)
assert_raises(nx.NetworkXUnfeasible, nx.capacity_scaling, G)
- G.node[0]['demand'] = 0
+ G.nodes[0]['demand'] = 0
G.add_node(1, demand=0)
G.add_edge(0, 1, weight=-float('inf'))
assert_raises(nx.NetworkXError, nx.network_simplex, G)