summaryrefslogtreecommitdiff
path: root/networkx/algorithms
diff options
context:
space:
mode:
authorJeffrey Finkelstein <jeffrey.finkelstein@gmail.com>2015-05-19 21:50:48 -0400
committerJeffrey Finkelstein <jeffrey.finkelstein@gmail.com>2015-07-17 01:36:27 -0400
commit2f70ad71c5c9bf5e1929f78fc5f0d25c397a7652 (patch)
tree9a43d466411201f12c5e18d647d281640a023a7c /networkx/algorithms
parent1bba0a9aaeac331d735247eb0ddad281f1b0d44e (diff)
downloadnetworkx-2f70ad71c5c9bf5e1929f78fc5f0d25c397a7652.tar.gz
Use peek(S) instead of next(iter(S)).
As of the date of this commit, there is no way to get an arbitrary element of an iterable like a set without modifying it (for example, as in `set.pop()`). The `peek()` function is more readable than writing next(iter(S)) whenever an arbitrary element of an iterable is required.
Diffstat (limited to 'networkx/algorithms')
-rw-r--r--networkx/algorithms/approximation/ramsey.py4
-rw-r--r--networkx/algorithms/cluster.py28
-rw-r--r--networkx/algorithms/components/connected.py3
-rw-r--r--networkx/algorithms/connectivity/connectivity.py5
-rw-r--r--networkx/algorithms/connectivity/stoerwagner.py16
-rw-r--r--networkx/algorithms/dag.py11
-rw-r--r--networkx/algorithms/euler.py30
-rw-r--r--networkx/algorithms/flow/capacityscaling.py8
-rw-r--r--networkx/algorithms/flow/preflowpush.py12
-rw-r--r--networkx/algorithms/minors.py18
-rw-r--r--networkx/algorithms/tests/test_minors.py5
-rw-r--r--networkx/algorithms/tests/test_simple_paths.py3
12 files changed, 81 insertions, 62 deletions
diff --git a/networkx/algorithms/approximation/ramsey.py b/networkx/algorithms/approximation/ramsey.py
index 03535ce9..14a70429 100644
--- a/networkx/algorithms/approximation/ramsey.py
+++ b/networkx/algorithms/approximation/ramsey.py
@@ -7,6 +7,8 @@ Ramsey numbers.
# All rights reserved.
# BSD license.
import networkx as nx
+from ...utils import arbitrary_element
+
__all__ = ["ramsey_R2"]
__author__ = """Nicholas Mancuso (nick.mancuso@gmail.com)"""
@@ -26,7 +28,7 @@ def ramsey_R2(G):
if not G:
return (set([]), set([]))
- node = next(G.nodes_iter())
+ node = arbitrary_element(G)
nbrs = nx.all_neighbors(G, node)
nnbrs = nx.non_neighbors(G, node)
c_1, i_1 = ramsey_R2(G.subgraph(nbrs))
diff --git a/networkx/algorithms/cluster.py b/networkx/algorithms/cluster.py
index 8947b3cd..89c3254b 100644
--- a/networkx/algorithms/cluster.py
+++ b/networkx/algorithms/cluster.py
@@ -1,21 +1,28 @@
# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2004-2015 by
+# Aric Hagberg <hagberg@lanl.gov>
+# Dan Schult <dschult@colgate.edu>
+# Pieter Swart <swart@lanl.gov>
+# All rights reserved.
+# BSD license.
"""Algorithms to characterize the number of triangles in a graph."""
from itertools import combinations
+
import networkx as nx
from networkx import NetworkXError
+from ..utils import not_implemented_for
+
__author__ = """\n""".join(['Aric Hagberg <aric.hagberg@gmail.com>',
'Dan Schult (dschult@colgate.edu)',
'Pieter Swart (swart@lanl.gov)',
'Jordi Torrents <jtorrents@milnou.net>'])
-# Copyright (C) 2004-2015 by
-# Aric Hagberg <hagberg@lanl.gov>
-# Dan Schult <dschult@colgate.edu>
-# Pieter Swart <swart@lanl.gov>
-# All rights reserved.
-# BSD license.
+
__all__= ['triangles', 'average_clustering', 'clustering', 'transitivity',
'square_clustering']
+
+@not_implemented_for('directed')
def triangles(G, nodes=None):
"""Compute the number of triangles.
@@ -49,12 +56,13 @@ def triangles(G, nodes=None):
three times, once at each node. Self loops are ignored.
"""
- if G.is_directed():
- raise NetworkXError("triangles() is not defined for directed graphs.")
+ # If `nodes` represents a single node in the graph, return only its number
+ # of triangles.
if nodes in G:
- # return single value
return next(_triangles_and_degree_iter(G,nodes))[2] // 2
- return dict( (v,t // 2) for v,d,t in _triangles_and_degree_iter(G,nodes))
+ # Otherwise, `nodes` represents an iterable of nodes, so return a
+ # dictionary mapping node to number of triangles.
+ return {v: t // 2 for v, d, t in _triangles_and_degree_iter(G, nodes)}
def _triangles_and_degree_iter(G,nodes=None):
""" Return an iterator of (node, degree, triangles).
diff --git a/networkx/algorithms/components/connected.py b/networkx/algorithms/components/connected.py
index 45398538..7280b1b9 100644
--- a/networkx/algorithms/components/connected.py
+++ b/networkx/algorithms/components/connected.py
@@ -10,6 +10,7 @@ Connected components.
# BSD license.
import networkx as nx
from networkx.utils.decorators import not_implemented_for
+from ...utils import arbitrary_element
__authors__ = "\n".join(['Eben Kenah',
'Aric Hagberg <aric.hagberg@gmail.com>'
@@ -170,7 +171,7 @@ def is_connected(G):
if len(G) == 0:
raise nx.NetworkXPointlessConcept('Connectivity is undefined ',
'for the null graph.')
- return len(set(_plain_bfs(G, next(G.nodes_iter())))) == len(G)
+ return len(set(_plain_bfs(G, arbitrary_element(G)))) == len(G)
@not_implemented_for('directed')
diff --git a/networkx/algorithms/connectivity/connectivity.py b/networkx/algorithms/connectivity/connectivity.py
index 51fbfea3..a16e1f18 100644
--- a/networkx/algorithms/connectivity/connectivity.py
+++ b/networkx/algorithms/connectivity/connectivity.py
@@ -5,6 +5,7 @@ Flow based connectivity algorithms
from __future__ import division
import itertools
+from operator import itemgetter
import networkx as nx
# Define the default maximum flow function to use in all flow based
@@ -325,9 +326,7 @@ def node_connectivity(G, s=None, t=None, flow_func=None):
kwargs = dict(flow_func=flow_func, auxiliary=H, residual=R)
# Pick a node with minimum degree
- degree = G.degree()
- minimum_degree = min(degree.values())
- v = next(n for n, d in degree.items() if d == minimum_degree)
+ v, minimum_degree = min(G.degree().items(), key=itemgetter(1))
# Node connectivity is bounded by degree.
K = minimum_degree
# compute local node connectivity with all its non-neighbors nodes
diff --git a/networkx/algorithms/connectivity/stoerwagner.py b/networkx/algorithms/connectivity/stoerwagner.py
index 50498a39..28268904 100644
--- a/networkx/algorithms/connectivity/stoerwagner.py
+++ b/networkx/algorithms/connectivity/stoerwagner.py
@@ -1,16 +1,20 @@
# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2014
+# ysitu <ysitu@users.noreply.github.com>
+# All rights reserved.
+# BSD license.
"""
Stoer-Wagner minimum cut algorithm.
"""
from itertools import islice
+
import networkx as nx
-from networkx.utils import *
+from ...utils import BinaryHeap
+from ...utils import not_implemented_for
+from ...utils import arbitrary_element
__author__ = 'ysitu <ysitu@users.noreply.github.com>'
-# Copyright (C) 2014
-# ysitu <ysitu@users.noreply.github.com>
-# All rights reserved.
-# BSD license.
__all__ = ['stoer_wagner']
@@ -109,7 +113,7 @@ def stoer_wagner(G, weight='weight', heap=BinaryHeap):
# Repeatedly pick a pair of nodes to contract until only one node is left.
for i in range(n - 1):
# Pick an arbitrary node u and create a set A = {u}.
- u = next(iter(G))
+ u = arbitrary_element(G)
A = set([u])
# Repeatedly pick the node "most tightly connected" to A and add it to
# A. The tightness of connectivity of a node not in A is defined by the
diff --git a/networkx/algorithms/dag.py b/networkx/algorithms/dag.py
index ac138f62..5666cc5c 100644
--- a/networkx/algorithms/dag.py
+++ b/networkx/algorithms/dag.py
@@ -1,7 +1,4 @@
# -*- coding: utf-8 -*-
-from fractions import gcd
-import networkx as nx
-from networkx.utils.decorators import *
"""Algorithms for directed acyclic graphs (DAGs)."""
# Copyright (C) 2006-2011 by
# Aric Hagberg <hagberg@lanl.gov>
@@ -9,6 +6,12 @@ from networkx.utils.decorators import *
# Pieter Swart <swart@lanl.gov>
# All rights reserved.
# BSD license.
+from fractions import gcd
+
+import networkx as nx
+from networkx.utils.decorators import *
+from ..utils import arbitrary_element
+
__author__ = """\n""".join(['Aric Hagberg <aric.hagberg@gmail.com>',
'Dan Schult (dschult@colgate.edu)',
'Ben Edwards (bedwards@cs.unm.edu)'])
@@ -279,7 +282,7 @@ def is_aperiodic(G):
raise nx.NetworkXError(
"is_aperiodic not defined for undirected graphs")
- s = next(G.nodes_iter())
+ s = arbitrary_element(G)
levels = {s: 0}
this_level = [s]
g = 0
diff --git a/networkx/algorithms/euler.py b/networkx/algorithms/euler.py
index c65abfc4..afa99e41 100644
--- a/networkx/algorithms/euler.py
+++ b/networkx/algorithms/euler.py
@@ -1,20 +1,24 @@
# -*- coding: utf-8 -*-
+#
+# Copyright (C) 2010 by
+# Aric Hagberg <hagberg@lanl.gov>
+# Dan Schult <dschult@colgate.edu>
+# Pieter Swart <swart@lanl.gov>
+# All rights reserved.
+# BSD license.
"""
Eulerian circuits and graphs.
"""
import networkx as nx
+from ..utils import arbitrary_element
+
__author__ = """\n""".join(['Nima Mohammadi (nima.irt[AT]gmail.com)',
'Aric Hagberg <hagberg@lanl.gov>'])
-# Copyright (C) 2010 by
-# Aric Hagberg <hagberg@lanl.gov>
-# Dan Schult <dschult@colgate.edu>
-# Pieter Swart <swart@lanl.gov>
-# All rights reserved.
-# BSD license.
__all__ = ['is_eulerian', 'eulerian_circuit']
+
def is_eulerian(G):
"""Return True if G is an Eulerian graph, False otherwise.
@@ -43,13 +47,13 @@ def is_eulerian(G):
# Every node must have equal in degree and out degree
for n in G.nodes_iter():
if G.in_degree(n) != G.out_degree(n):
- return False
+ return False
# Must be strongly connected
if not nx.is_strongly_connected(G):
return False
else:
# An undirected Eulerian graph has no vertices of odd degrees
- for v,d in G.degree_iter():
+ for v, d in G.degree_iter():
if d % 2 != 0:
return False
# Must be connected
@@ -110,11 +114,11 @@ def eulerian_circuit(G, source=None):
from operator import itemgetter
if not is_eulerian(G):
raise nx.NetworkXError("G is not Eulerian.")
- g = G.__class__(G) # copy graph structure (not attributes)
+ g = G.__class__(G) # copy graph structure (not attributes)
# set starting node
if source is None:
- v = next(g.nodes_iter())
+ v = arbitrary_element(g)
else:
v = source
@@ -137,6 +141,6 @@ def eulerian_circuit(G, source=None):
last_vertex = current_vertex
vertex_stack.pop()
else:
- random_edge = next(edges(current_vertex))
- vertex_stack.append(get_vertex(random_edge))
- g.remove_edge(*random_edge)
+ arbitrary_edge = next(edges(current_vertex))
+ vertex_stack.append(get_vertex(arbitrary_edge))
+ g.remove_edge(*arbitrary_edge)
diff --git a/networkx/algorithms/flow/capacityscaling.py b/networkx/algorithms/flow/capacityscaling.py
index 357dad76..3bf996d4 100644
--- a/networkx/algorithms/flow/capacityscaling.py
+++ b/networkx/algorithms/flow/capacityscaling.py
@@ -13,8 +13,10 @@ __all__ = ['capacity_scaling']
from itertools import chain
from math import log
import networkx as nx
-from networkx.utils import *
-
+from ...utils import BinaryHeap
+from ...utils import generate_unique_node
+from ...utils import not_implemented_for
+from ...utils import arbitrary_element
def _detect_unboundedness(R):
"""Detect infinite-capacity negative cycles.
@@ -308,7 +310,7 @@ def capacity_scaling(G, demand='demand', capacity='capacity', weight='weight',
# Repeatedly augment flow from S to T along shortest paths until
# Δ-feasibility is achieved.
while S and T:
- s = next(iter(S))
+ s = arbitrary_element(S)
t = None
# Search for a shortest path in terms of reduce costs from s to
# any t in T in the Δ-residual network.
diff --git a/networkx/algorithms/flow/preflowpush.py b/networkx/algorithms/flow/preflowpush.py
index 3db0ae09..6bb3e4a0 100644
--- a/networkx/algorithms/flow/preflowpush.py
+++ b/networkx/algorithms/flow/preflowpush.py
@@ -11,7 +11,13 @@ __author__ = """ysitu <ysitu@users.noreply.github.com>"""
from collections import deque
from itertools import islice
import networkx as nx
-from networkx.algorithms.flow.utils import *
+#from networkx.algorithms.flow.utils import *
+from ...utils import arbitrary_element
+from .utils import build_residual_network
+from .utils import CurrentEdge
+from .utils import detect_unboundedness
+from .utils import GlobalRelabelThreshold
+from .utils import Level
__all__ = ['preflow_push']
@@ -233,7 +239,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
# Record the old height and level for the gap heuristic.
old_height = height
old_level = level
- u = next(iter(level.active))
+ u = arbitrary_element(level.active)
height = discharge(u, True)
if grt.is_reached():
# Global relabeling heuristic: Recompute the exact heights of
@@ -277,7 +283,7 @@ def preflow_push_impl(G, s, t, capacity, residual, global_relabel_freq,
# Move to the next lower level.
height -= 1
break
- u = next(iter(level.active))
+ u = arbitrary_element(level.active)
height = discharge(u, False)
if grt.is_reached():
# Global relabeling heuristic.
diff --git a/networkx/algorithms/minors.py b/networkx/algorithms/minors.py
index f91c0be4..197e62d3 100644
--- a/networkx/algorithms/minors.py
+++ b/networkx/algorithms/minors.py
@@ -12,24 +12,12 @@ from itertools import combinations
from itertools import permutations
from itertools import product
+from ..utils import arbitrary_element
+
__all__ = ['contracted_edge', 'contracted_nodes',
'identified_nodes', 'quotient_graph']
-def peek(iterable):
- """Returns an arbitrary element of ``iterable`` without removing it.
-
- This is most useful for peeking at an arbitrary element of a set::
-
- >>> peek({3, 2, 1})
- 1
- >>> peek('hello')
- 'h'
-
- """
- return next(iter(iterable))
-
-
def equivalence_classes(iterable, relation):
"""Returns the set of equivalence classes of the given ``iterable`` under
the specified equivalence relation.
@@ -53,7 +41,7 @@ def equivalence_classes(iterable, relation):
#
# Each block is guaranteed to be non-empty
for block in blocks:
- x = peek(block)
+ x = arbitrary_element(block)
if relation(x, y):
block.append(y)
break
diff --git a/networkx/algorithms/tests/test_minors.py b/networkx/algorithms/tests/test_minors.py
index 44ae7069..79a1411b 100644
--- a/networkx/algorithms/tests/test_minors.py
+++ b/networkx/algorithms/tests/test_minors.py
@@ -12,6 +12,7 @@ from nose.tools import assert_true
from nose.tools import raises
import networkx as nx
+from networkx.utils import arbitrary_element
class TestQuotient(object):
@@ -57,8 +58,8 @@ class TestQuotient(object):
"""
G = nx.path_graph(5)
identity = lambda u, v: u == v
- peek = lambda x: next(iter(x))
- same_parity = lambda b, c: peek(b) % 2 == peek(c) % 2
+ same_parity = lambda b, c: (arbitrary_element(b) % 2
+ == arbitrary_element(c) % 2)
actual = nx.quotient_graph(G, identity, same_parity)
expected = nx.Graph()
expected.add_edges_from([(0, 2), (0, 4), (2, 4)])
diff --git a/networkx/algorithms/tests/test_simple_paths.py b/networkx/algorithms/tests/test_simple_paths.py
index 81531763..c068c70a 100644
--- a/networkx/algorithms/tests/test_simple_paths.py
+++ b/networkx/algorithms/tests/test_simple_paths.py
@@ -6,6 +6,7 @@ import networkx as nx
from networkx import convert_node_labels_to_integers as cnlti
from networkx.algorithms.simple_paths import _bidirectional_shortest_path
from networkx.algorithms.simple_paths import _bidirectional_dijkstra
+from networkx.utils import arbitrary_element
# Tests for all_simple_paths
def test_all_simple_paths():
@@ -44,7 +45,7 @@ def test_all_simple_paths_empty():
assert_equal(list(list(p) for p in paths),[])
def hamiltonian_path(G,source):
- source = next(G.nodes_iter())
+ source = arbitrary_element(G)
neighbors = set(G[source])-set([source])
n = len(G)
for target in neighbors: