summaryrefslogtreecommitdiff
path: root/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/cycles.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/python2.7/site-packages/setoolsgui/networkx/algorithms/cycles.py')
-rw-r--r--lib/python2.7/site-packages/setoolsgui/networkx/algorithms/cycles.py317
1 files changed, 317 insertions, 0 deletions
diff --git a/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/cycles.py b/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/cycles.py
new file mode 100644
index 0000000..4955538
--- /dev/null
+++ b/lib/python2.7/site-packages/setoolsgui/networkx/algorithms/cycles.py
@@ -0,0 +1,317 @@
+"""
+========================
+Cycle finding algorithms
+========================
+"""
+# Copyright (C) 2010-2012 by
+# Aric Hagberg <hagberg@lanl.gov>
+# Dan Schult <dschult@colgate.edu>
+# Pieter Swart <swart@lanl.gov>
+# All rights reserved.
+# BSD license.
+import networkx as nx
+from networkx.utils import *
+from collections import defaultdict
+
+__all__ = ['cycle_basis','simple_cycles','recursive_simple_cycles']
+__author__ = "\n".join(['Jon Olav Vik <jonovik@gmail.com>',
+ 'Dan Schult <dschult@colgate.edu>',
+ 'Aric Hagberg <hagberg@lanl.gov>'])
+
+@not_implemented_for('directed')
+@not_implemented_for('multigraph')
+def cycle_basis(G,root=None):
+ """ Returns a list of cycles which form a basis for cycles of G.
+
+ A basis for cycles of a network is a minimal collection of
+ cycles such that any cycle in the network can be written
+ as a sum of cycles in the basis. Here summation of cycles
+ is defined as "exclusive or" of the edges. Cycle bases are
+ useful, e.g. when deriving equations for electric circuits
+ using Kirchhoff's Laws.
+
+ Parameters
+ ----------
+ G : NetworkX Graph
+ root : node, optional
+ Specify starting node for basis.
+
+ Returns
+ -------
+ A list of cycle lists. Each cycle list is a list of nodes
+ which forms a cycle (loop) in G.
+
+ Examples
+ --------
+ >>> G=nx.Graph()
+ >>> G.add_cycle([0,1,2,3])
+ >>> G.add_cycle([0,3,4,5])
+ >>> print(nx.cycle_basis(G,0))
+ [[3, 4, 5, 0], [1, 2, 3, 0]]
+
+ Notes
+ -----
+ This is adapted from algorithm CACM 491 [1]_.
+
+ References
+ ----------
+ .. [1] Paton, K. An algorithm for finding a fundamental set of
+ cycles of a graph. Comm. ACM 12, 9 (Sept 1969), 514-518.
+
+ See Also
+ --------
+ simple_cycles
+ """
+ gnodes=set(G.nodes())
+ cycles=[]
+ while gnodes: # loop over connected components
+ if root is None:
+ root=gnodes.pop()
+ stack=[root]
+ pred={root:root}
+ used={root:set()}
+ while stack: # walk the spanning tree finding cycles
+ z=stack.pop() # use last-in so cycles easier to find
+ zused=used[z]
+ for nbr in G[z]:
+ if nbr not in used: # new node
+ pred[nbr]=z
+ stack.append(nbr)
+ used[nbr]=set([z])
+ elif nbr == z: # self loops
+ cycles.append([z])
+ elif nbr not in zused:# found a cycle
+ pn=used[nbr]
+ cycle=[nbr,z]
+ p=pred[z]
+ while p not in pn:
+ cycle.append(p)
+ p=pred[p]
+ cycle.append(p)
+ cycles.append(cycle)
+ used[nbr].add(z)
+ gnodes-=set(pred)
+ root=None
+ return cycles
+
+
+@not_implemented_for('undirected')
+def simple_cycles(G):
+ """Find simple cycles (elementary circuits) of a directed graph.
+
+ An simple cycle, or elementary circuit, is a closed path where no
+ node appears twice, except that the first and last node are the same.
+ Two elementary circuits are distinct if they are not cyclic permutations
+ of each other.
+
+ This is a nonrecursive, iterator/generator version of Johnson's
+ algorithm [1]_. There may be better algorithms for some cases [2]_ [3]_.
+
+ Parameters
+ ----------
+ G : NetworkX DiGraph
+ A directed graph
+
+ Returns
+ -------
+ cycle_generator: generator
+ A generator that produces elementary cycles of the graph. Each cycle is
+ a list of nodes with the first and last nodes being the same.
+
+ Examples
+ --------
+ >>> G = nx.DiGraph([(0, 0), (0, 1), (0, 2), (1, 2), (2, 0), (2, 1), (2, 2)])
+ >>> list(nx.simple_cycles(G))
+ [[2], [2, 1], [2, 0], [2, 0, 1], [0]]
+
+ Notes
+ -----
+ The implementation follows pp. 79-80 in [1]_.
+
+ The time complexity is O((n+e)(c+1)) for n nodes, e edges and c
+ elementary circuits.
+
+ To filter the cycles so that they don't include certain nodes or edges,
+ copy your graph and eliminate those nodes or edges before calling.
+ >>> copyG = G.copy()
+ >>> copyG.remove_nodes_from([1])
+ >>> copyG.remove_edges_from([(0,1)])
+ >>> list(nx.simple_cycles(copyG))
+ [[2], [2, 0], [0]]
+
+ References
+ ----------
+ .. [1] Finding all the elementary circuits of a directed graph.
+ D. B. Johnson, SIAM Journal on Computing 4, no. 1, 77-84, 1975.
+ http://dx.doi.org/10.1137/0204007
+
+ .. [2] Enumerating the cycles of a digraph: a new preprocessing strategy.
+ G. Loizou and P. Thanish, Information Sciences, v. 27, 163-182, 1982.
+
+ .. [3] A search strategy for the elementary cycles of a directed graph.
+ J.L. Szwarcfiter and P.E. Lauer, BIT NUMERICAL MATHEMATICS,
+ v. 16, no. 2, 192-204, 1976.
+
+ See Also
+ --------
+ cycle_basis
+ """
+ def _unblock(thisnode,blocked,B):
+ stack=set([thisnode])
+ while stack:
+ node=stack.pop()
+ if node in blocked:
+ blocked.remove(node)
+ stack.update(B[node])
+ B[node].clear()
+
+ # Johnson's algorithm requires some ordering of the nodes.
+ # We assign the arbitrary ordering given by the strongly connected comps
+ # There is no need to track the ordering as each node removed as processed.
+ subG=G.copy() # save the actual graph so we can mutate it here
+ sccs = nx.strongly_connected_components(subG)
+ while sccs:
+ scc=sccs.pop()
+ # order of scc determines ordering of nodes
+ startnode = scc.pop()
+ # Processing node runs "circuit" routine from recursive version
+ path=[startnode]
+ blocked = set() # vertex: blocked from search?
+ closed = set() # nodes involved in a cycle
+ blocked.add(startnode)
+ B=defaultdict(set) # graph portions that yield no elementary circuit
+ stack=[ (startnode,list(subG[startnode])) ] # subG gives component nbrs
+ while stack:
+ thisnode,nbrs = stack[-1]
+ if nbrs:
+ nextnode = nbrs.pop()
+# print thisnode,nbrs,":",nextnode,blocked,B,path,stack,startnode
+# f=raw_input("pause")
+ if nextnode == startnode:
+ yield path[:]
+ closed.update(path)
+# print "Found a cycle",path,closed
+ elif nextnode not in blocked:
+ path.append(nextnode)
+ stack.append( (nextnode,list(subG[nextnode])) )
+ blocked.add(nextnode)
+ continue
+ # done with nextnode... look for more neighbors
+ if not nbrs: # no more nbrs
+ if thisnode in closed:
+ _unblock(thisnode,blocked,B)
+ else:
+ for nbr in G[thisnode]:
+ if thisnode not in B[nbr]:
+ B[nbr].add(thisnode)
+ stack.pop()
+# assert path[-1]==thisnode
+ path.pop()
+ # done processing this node
+ subG.remove_node(startnode)
+ H=subG.subgraph(scc) # make smaller to avoid work in SCC routine
+ sccs.extend(nx.strongly_connected_components(H))
+
+
+@not_implemented_for('undirected')
+def recursive_simple_cycles(G):
+ """Find simple cycles (elementary circuits) of a directed graph.
+
+ A simple cycle, or elementary circuit, is a closed path where no
+ node appears twice, except that the first and last node are the same.
+ Two elementary circuits are distinct if they are not cyclic permutations
+ of each other.
+
+ This version uses a recursive algorithm to build a list of cycles.
+ You should probably use the iterator version caled simple_cycles().
+ Warning: This recursive version uses lots of RAM!
+
+ Parameters
+ ----------
+ G : NetworkX DiGraph
+ A directed graph
+
+ Returns
+ -------
+ A list of circuits, where each circuit is a list of nodes, with the first
+ and last node being the same.
+
+ Example:
+ >>> G = nx.DiGraph([(0, 0), (0, 1), (0, 2), (1, 2), (2, 0), (2, 1), (2, 2)])
+ >>> nx.recursive_simple_cycles(G)
+ [[0], [0, 1, 2], [0, 2], [1, 2], [2]]
+
+ See Also
+ --------
+ cycle_basis (for undirected graphs)
+
+ Notes
+ -----
+ The implementation follows pp. 79-80 in [1]_.
+
+ The time complexity is O((n+e)(c+1)) for n nodes, e edges and c
+ elementary circuits.
+
+ References
+ ----------
+ .. [1] Finding all the elementary circuits of a directed graph.
+ D. B. Johnson, SIAM Journal on Computing 4, no. 1, 77-84, 1975.
+ http://dx.doi.org/10.1137/0204007
+
+ See Also
+ --------
+ simple_cycles, cycle_basis
+ """
+ # Jon Olav Vik, 2010-08-09
+ def _unblock(thisnode):
+ """Recursively unblock and remove nodes from B[thisnode]."""
+ if blocked[thisnode]:
+ blocked[thisnode] = False
+ while B[thisnode]:
+ _unblock(B[thisnode].pop())
+
+ def circuit(thisnode, startnode, component):
+ closed = False # set to True if elementary path is closed
+ path.append(thisnode)
+ blocked[thisnode] = True
+ for nextnode in component[thisnode]: # direct successors of thisnode
+ if nextnode == startnode:
+ result.append(path[:])
+ closed = True
+ elif not blocked[nextnode]:
+ if circuit(nextnode, startnode, component):
+ closed = True
+ if closed:
+ _unblock(thisnode)
+ else:
+ for nextnode in component[thisnode]:
+ if thisnode not in B[nextnode]: # TODO: use set for speedup?
+ B[nextnode].append(thisnode)
+ path.pop() # remove thisnode from path
+ return closed
+
+ path = [] # stack of nodes in current path
+ blocked = defaultdict(bool) # vertex: blocked from search?
+ B = defaultdict(list) # graph portions that yield no elementary circuit
+ result = [] # list to accumulate the circuits found
+ # Johnson's algorithm requires some ordering of the nodes.
+ # They might not be sortable so we assign an arbitrary ordering.
+ ordering=dict(zip(G,range(len(G))))
+ for s in ordering:
+ # Build the subgraph induced by s and following nodes in the ordering
+ subgraph = G.subgraph(node for node in G
+ if ordering[node] >= ordering[s])
+ # Find the strongly connected component in the subgraph
+ # that contains the least node according to the ordering
+ strongcomp = nx.strongly_connected_components(subgraph)
+ mincomp=min(strongcomp,
+ key=lambda nodes: min(ordering[n] for n in nodes))
+ component = G.subgraph(mincomp)
+ if component:
+ # smallest node in the component according to the ordering
+ startnode = min(component,key=ordering.__getitem__)
+ for node in component:
+ blocked[node] = False
+ B[node][:] = []
+ dummy=circuit(startnode, startnode, component)
+ return result