diff options
| author | Dan Schult <dschult@colgate.edu> | 2017-08-12 17:20:15 -0600 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2017-08-12 17:20:15 -0600 |
| commit | 2c6740efbebf56fc28686bc01c49f541f307d353 (patch) | |
| tree | 5c6db5caf25b2dddfa4e0d3df4e35e1bd67d859e /networkx/algorithms/flow | |
| parent | d72aca7a92c7de6d854e50ec4dc7235842780490 (diff) | |
| download | networkx-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.py | 38 | ||||
| -rw-r--r-- | networkx/algorithms/flow/edmondskarp.py | 2 | ||||
| -rw-r--r-- | networkx/algorithms/flow/maxflow.py | 2 | ||||
| -rw-r--r-- | networkx/algorithms/flow/networksimplex.py | 12 | ||||
| -rw-r--r-- | networkx/algorithms/flow/preflowpush.py | 52 | ||||
| -rw-r--r-- | networkx/algorithms/flow/shortestaugmentingpath.py | 20 | ||||
| -rw-r--r-- | networkx/algorithms/flow/tests/test_mincost.py | 8 |
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) |
