summaryrefslogtreecommitdiff
path: root/networkx/convert.py
diff options
context:
space:
mode:
authoraric <none@none>2008-11-03 04:37:22 +0000
committeraric <none@none>2008-11-03 04:37:22 +0000
commitad25ae40af532158bf1d6765d0dc822d67bcbcb3 (patch)
tree117c94dec2a623c4cb6a89796ea2ac011880884b /networkx/convert.py
parent04c67c448187f61a32c3050b8de5b13b72d11e4e (diff)
downloadnetworkx-ad25ae40af532158bf1d6765d0dc822d67bcbcb3.tar.gz
Merged revisions 741-766,769-770,794-797,799,804-829,845-848,858-885 via svnmerge from
https://networkx.lanl.gov/svn/networkx/branches/pre99 ........ r741 | aric | 2008-02-18 18:29:21 -0700 (Mon, 18 Feb 2008) | 3 lines pre99 branch refactoring directory layout ........ r742 | aric | 2008-02-18 18:30:17 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: missing utils.py ........ r743 | aric | 2008-02-18 20:42:25 -0700 (Mon, 18 Feb 2008) | 7 lines pre99: graph,digraph,multigraph,multidigraph list functions in __init__ remove xgraph,xdigraph ........ r744 | aric | 2008-02-18 20:42:58 -0700 (Mon, 18 Feb 2008) | 3 lines pre99: example of labeled graphs ........ r745 | aric | 2008-02-18 20:44:46 -0700 (Mon, 18 Feb 2008) | 5 lines pre99: tests for graph,digraph,multigraph,multidigraph uses nose - run with nosetests ........ r746 | aric | 2008-02-18 20:45:23 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: __init__ for classes ........ r747 | aric | 2008-02-18 20:47:51 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: multigraph and multidigraph ........ r748 | aric | 2008-02-18 20:48:37 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: move operator -> operators ........ r749 | aric | 2008-02-18 20:49:38 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: add _all__ and fix complete graph to work with selfloops on ........ r750 | aric | 2008-02-18 20:50:19 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: update utils header ........ r751 | aric | 2008-02-18 21:02:25 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: use __all__ and G.is_directed() -> G.directed ........ r752 | aric | 2008-02-18 21:03:33 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: linalg uses __all__ ........ r753 | aric | 2008-02-18 21:38:34 -0700 (Mon, 18 Feb 2008) | 2 lines pre99 : define __all__ and use for imports in __init__ ........ r754 | aric | 2008-02-18 21:51:29 -0700 (Mon, 18 Feb 2008) | 2 lines pre99: adjust imports in isomorph.py ........ r755 | aric | 2008-02-18 21:52:37 -0700 (Mon, 18 Feb 2008) | 3 lines pre99: An old doctest test, modified. ........ r756 | aric | 2008-02-19 07:03:31 -0700 (Tue, 19 Feb 2008) | 2 lines pre99: fix imports in generators ........ r757 | aric | 2008-02-19 18:51:15 -0700 (Tue, 19 Feb 2008) | 2 lines pre99: NEP2 version of convert.py ........ r758 | aric | 2008-02-19 18:52:07 -0700 (Tue, 19 Feb 2008) | 2 lines pre99: adjust imports in isomorph.py ........ r759 | aric | 2008-02-19 18:52:50 -0700 (Tue, 19 Feb 2008) | 2 lines pre99: add DiGraphMatcher to imports ........ r760 | aric | 2008-02-19 18:53:22 -0700 (Tue, 19 Feb 2008) | 2 lines pre99: add digraph edges_iter() ........ r761 | aric | 2008-02-19 18:54:52 -0700 (Tue, 19 Feb 2008) | 2 lines pre99: tests for digraph edges_iter ........ r762 | aric | 2008-02-19 18:55:36 -0700 (Tue, 19 Feb 2008) | 2 lines pre99: add (modified) legacy digraph doctests ........ r763 | dschult | 2008-02-23 15:15:11 -0700 (Sat, 23 Feb 2008) | 3 lines pre99: Update convert.py and convert.txt to pre99 API from NEP2 style. ........ r764 | dschult | 2008-02-23 17:28:59 -0700 (Sat, 23 Feb 2008) | 3 lines pre99: Fix up the other (scipy and numpy) tests for convert.py ........ r765 | dschult | 2008-02-23 17:46:51 -0700 (Sat, 23 Feb 2008) | 3 lines pre99: Revision of info.py to reflect pre99 API. ........ r766 | dschult | 2008-02-23 21:37:13 -0700 (Sat, 23 Feb 2008) | 12 lines pre99: a few minor code tweaks. graph/digraph - revamp adjaccency_list to give order of G.nodes() and not use _helper() - remove extra code in degree_iter - speedup in degree/in_degree/out_degree - speedup in subgraph multigraph/multidigraph - get_edgedata->get_edge in multi(di)graph ........ r769 | dschult | 2008-03-02 21:41:54 -0700 (Sun, 02 Mar 2008) | 6 lines pre99: cleanup classes Change usage of "delete" in code and docs to "remove". In MultiGraph/MulriDiGraph use super(...). instead of Graph. or DiGraph. ........ r770 | dschult | 2008-03-02 21:44:30 -0700 (Sun, 02 Mar 2008) | 6 lines pre99: Simplify LabeledGraph code slightly using super(...) LabeledDiGraph now only inherits. No new code. Should do similar for Multi versions. But should they be in separate files, or all in one file? ........ r794 | dschult | 2008-07-11 16:58:43 -0600 (Fri, 11 Jul 2008) | 1 line Changes in docstrings for graph.py ........ r795 | dschult | 2008-07-11 17:00:53 -0600 (Fri, 11 Jul 2008) | 3 lines fix subgraph bug and add tests (mistakenly added last commit) ........ r796 | dschult | 2008-07-11 18:08:45 -0600 (Fri, 11 Jul 2008) | 8 lines Fixed tests for prepare_nbunch and then had to fix code because creating the iterator doesn't catch nonsequence errors until iterator is used. Added more tests for add_edges_from and some code to catch errors in add_edges_from(). ........ r797 | dschult | 2008-07-11 20:28:07 -0600 (Fri, 11 Jul 2008) | 3 lines Add subgraph and tests for subgraph in digraph,multigraph and dimultigraph. ........ r799 | dschult | 2008-07-14 23:21:18 -0600 (Mon, 14 Jul 2008) | 12 lines Create nbunch as set in subgraph in Graph and DiGraph. Remove DiGraph docstrings that are identical to Graph docstrings. Some DiGraph code changes to fix data in add_edges_from and remove unnecessary checks for selfloops in remove_node. Add doc that to_undirected() isn't well-defined if edge data in two directions isn't the same. Tests update for removing nodes when selfloops present. ........ r804 | dschult | 2008-08-11 22:33:03 -0600 (Mon, 11 Aug 2008) | 6 lines Added labeledgraph to imports, updated info graph and convert docstrings. replaced list comprehension with iterator comprehension in graph. Updated operators.py so that it at least works with the tests. ........ r805 | dschult | 2008-08-13 21:43:22 -0600 (Wed, 13 Aug 2008) | 3 lines Update centrality for pre99 classes and update tests. ........ r806 | dschult | 2008-08-13 22:26:36 -0600 (Wed, 13 Aug 2008) | 3 lines Update clique for pre99. ........ r807 | dschult | 2008-08-13 22:27:57 -0600 (Wed, 13 Aug 2008) | 1 line Change name of cliques test file. ........ r808 | dschult | 2008-08-13 23:55:55 -0600 (Wed, 13 Aug 2008) | 4 lines Updated core.py for pre99. Rewrote much of cluster.py to reuse a single iterator/helper function. ........ r809 | dschult | 2008-08-14 00:52:04 -0600 (Thu, 14 Aug 2008) | 3 lines Update traversal modules for pre99 along with tests. ........ r810 | dschult | 2008-08-14 01:08:02 -0600 (Thu, 14 Aug 2008) | 1 line Updated isomorphism algorithms for pre99. ........ r811 | dschult | 2008-08-14 02:42:58 -0600 (Thu, 14 Aug 2008) | 1 line Updated generators modules for pre99 to pass tests. ........ r812 | dschult | 2008-08-14 10:02:22 -0600 (Thu, 14 Aug 2008) | 4 lines One bug fix and some tweaks in convert. We probably need more tests here especially Graph to MultiDiGraph, etc.. ........ r813 | dschult | 2008-08-14 10:42:59 -0600 (Thu, 14 Aug 2008) | 11 lines Remove to_directed and to_undirected methods. I spent too much time comparing DiGraph(G) to G.to_directed() and even with lots of fiddling I couldn't get the methods to be faster than the from_whatever. As written, they are 2-3 times slower. We wanted to get rid of them anyway and it looks like convert is ready for that. I also adjusted LabeledGraph so that LabeledGraph(LG) copies the labels as well as the graph. ........ r814 | dschult | 2008-08-14 12:14:55 -0600 (Thu, 14 Aug 2008) | 7 lines Simplify the copy() method by using convert. Have to change from_whatever() to copy the self.weighted attribute. Decided not to have it copy the name too... Too complicated and not sure that copying the name is the best/natural choice. Users can copy it outside of from_whatever() if they want. ........ r815 | dschult | 2008-08-14 12:36:55 -0600 (Thu, 14 Aug 2008) | 7 lines Changed the keyword for subgraph from copy=True to newgraph=True. It used to be inplace=False. Copy has too many other meanings in this package. Not sure that newgraph is the best though either. I'd prefer to take out the option of making a subgraph by deleting nodes. That's what delete_nodes_from is for. ........ r816 | dschult | 2008-08-14 13:26:40 -0600 (Thu, 14 Aug 2008) | 7 lines Change from_whatever() to identify NetworkX graphs using attribute 'adj' instead of 'add_node'. This will allow future e.g. scipy sparse matrix classes to use add_node without confusing from_whatever(). We really use thing.adj and not thing.add_node anyway. ........ r817 | aric | 2008-08-14 15:16:07 -0600 (Thu, 14 Aug 2008) | 2 lines change dates of copyright in README ........ r818 | dschult | 2008-08-14 15:19:52 -0600 (Thu, 14 Aug 2008) | 1 line Updated readwrite/adjlist.py to pre99. ........ r819 | dschult | 2008-08-14 22:32:30 -0600 (Thu, 14 Aug 2008) | 4 lines Back out (inverse merge) changeset 815 where subgraph(copy=True) became subgraph(newgraph=True). Following numpy.array we can use copy=True. ........ r820 | dschult | 2008-08-14 23:07:01 -0600 (Thu, 14 Aug 2008) | 3 lines Docstring correction... subgraph(copy=False) is a mutating method. ........ r821 | dschult | 2008-08-14 23:11:57 -0600 (Thu, 14 Aug 2008) | 9 lines Updated readwrite/edgelist for pre99 In the process realized that MultiDiGraph was using digraph's methods for edges_iter and remove_edges_from. (and shouldn't be) Added some tests to help with spotting this particular hole. How many others are there? :) ........ r822 | dschult | 2008-08-14 23:44:01 -0600 (Thu, 14 Aug 2008) | 3 lines Update remaining readwrite modules for pre99. ........ r823 | dschult | 2008-08-15 13:44:41 -0600 (Fri, 15 Aug 2008) | 3 lines Update linalg/spectrum.py to pre99. Actually only had to adjust the tests import statement. ........ r824 | dschult | 2008-08-15 15:07:06 -0600 (Fri, 15 Aug 2008) | 4 lines Reinstall to_(un)directed for pre99... Useful because you don't always know what type of graph you are converting to directed. ........ r825 | dschult | 2008-08-15 15:15:41 -0600 (Fri, 15 Aug 2008) | 4 lines More cleanup of to_undirected for pre99.... Also its not clear what to do with multiedges. Both directions means two undirected? ........ r826 | dschult | 2008-08-15 15:58:27 -0600 (Fri, 15 Aug 2008) | 5 lines Rename prepare_nbunch as nbunch_iter Use nbunch_iter more effectively for edges()... Now edges should be almost as fast as looking through all neighbors with adjacency_iter? ........ r827 | dschult | 2008-08-15 16:40:24 -0600 (Fri, 15 Aug 2008) | 4 lines Update tree and drawing for pre99. All modules now pass the tests. ........ r828 | dschult | 2008-08-15 23:28:04 -0600 (Fri, 15 Aug 2008) | 5 lines Cleaning up documentation a little. In the process, realised that multidigraph was missing get_edge so put that in too. ........ r829 | dschult | 2008-08-16 00:27:03 -0600 (Sat, 16 Aug 2008) | 9 lines Based on examples, fixed some stuff in convert.py and nx_agraph. The examples haven't all been run. I did basic simple conversions to pre99: 1) look for XGraph and XDiGraph and change to Graph/MultiGraph depending. 2) look for .edges() and check if it wants three values returned (add data=True) 3) look for is_directed 4) look for multiedges and loops to see if we handle them correctly. ........ r845 | dschult | 2008-08-23 15:36:31 -0600 (Sat, 23 Aug 2008) | 5 lines Added utils to __all__ so from networkx import *;utils._get_fh() works. Removed import networkx from utils to avoid circular imports--perhaps utils should be treated like other modules in __all__? Small corrections for nx_agraph.py and examples/unixemail.py ........ r846 | dschult | 2008-08-23 20:31:37 -0600 (Sat, 23 Aug 2008) | 3 lines Upate documentation docs for pre99. ........ r847 | dschult | 2008-08-23 22:02:14 -0600 (Sat, 23 Aug 2008) | 5 lines Add methods add_path, add_cycle back into base class; new method add_star. Put edge_boundary and node_boundary into algorithms module called boundary.py ........ r848 | dschult | 2008-08-23 22:10:53 -0600 (Sat, 23 Aug 2008) | 3 lines Put add_star() method into docs. ........ r858 | aric | 2008-10-21 21:19:31 -0600 (Tue, 21 Oct 2008) | 2 lines pre99 docstring formatting ........ r859 | aric | 2008-10-21 21:25:40 -0600 (Tue, 21 Oct 2008) | 2 lines pre99: beginning draft for sphinx-based documentation ........ r860 | aric | 2008-10-24 10:20:14 -0600 (Fri, 24 Oct 2008) | 3 lines adjust docstrings to use nx prefix, will use nose plugin that specifies "import networkx as nx" for testing ........ r861 | aric | 2008-10-24 10:38:25 -0600 (Fri, 24 Oct 2008) | 3 lines plugin for nose to give "import networkx as nx" context to docstrings in modules ........ r862 | aric | 2008-10-25 09:16:25 -0600 (Sat, 25 Oct 2008) | 4 lines remove test boilerplate in favor of nose, move tests to subdirecdtories with modules ........ r863 | aric | 2008-10-25 09:33:57 -0600 (Sat, 25 Oct 2008) | 2 lines move readwrite tests to subdirectory and remove testing boilerplate ........ r864 | aric | 2008-10-25 09:36:53 -0600 (Sat, 25 Oct 2008) | 2 lines mv linalg tests to subdirectory and remove testing boilerplate ........ r865 | aric | 2008-10-25 09:44:46 -0600 (Sat, 25 Oct 2008) | 2 lines mv algorithms tests to subdirectory and remove testing boilerplate ........ r866 | aric | 2008-10-25 10:00:48 -0600 (Sat, 25 Oct 2008) | 2 lines move base class tests to subdirectory (mostly unsed tests now) ........ r867 | aric | 2008-10-25 10:09:07 -0600 (Sat, 25 Oct 2008) | 2 lines update convert to modern scipy sparse interface, remove testing boilerplate ........ r868 | aric | 2008-10-25 10:34:52 -0600 (Sat, 25 Oct 2008) | 3 lines Clean up setup envieronment for tests. Use python setup_egg.py nosetests for testing ........ r869 | aric | 2008-10-28 08:03:21 -0600 (Tue, 28 Oct 2008) | 2 lines set ignore propedit ........ r870 | aric | 2008-10-28 08:08:06 -0600 (Tue, 28 Oct 2008) | 2 lines adjust svn:ignore on refrence/generated ........ r871 | aric | 2008-10-28 08:10:54 -0600 (Tue, 28 Oct 2008) | 2 lines add front page sphinx templates ........ r872 | aric | 2008-10-28 08:16:05 -0600 (Tue, 28 Oct 2008) | 3 lines Add numpy sphinx extensions from http://sphinx.googlecode.com/svn/contrib/trunk/numpyext sphinxext/numpyext ........ r873 | aric | 2008-10-28 08:17:08 -0600 (Tue, 28 Oct 2008) | 2 lines add missing file from numpy sphinx extensions ........ r874 | aric | 2008-10-28 08:48:11 -0600 (Tue, 28 Oct 2008) | 2 lines reorganize sphinx documentation ........ r875 | aric | 2008-10-29 09:01:12 -0600 (Wed, 29 Oct 2008) | 5 lines remove __all__ from __init__'s in favor of simpler from import add test runner in test/run.py ........ r876 | aric | 2008-11-01 09:02:56 -0600 (Sat, 01 Nov 2008) | 2 lines update pre99 sphinx docs ........ r877 | aric | 2008-11-01 09:03:43 -0600 (Sat, 01 Nov 2008) | 2 lines update documentation in several modules ........ r878 | aric | 2008-11-01 10:28:47 -0600 (Sat, 01 Nov 2008) | 2 lines update sphinx doc formatting ........ r879 | aric | 2008-11-01 11:04:30 -0600 (Sat, 01 Nov 2008) | 2 lines typo in conf.py ........ r880 | aric | 2008-11-01 11:05:31 -0600 (Sat, 01 Nov 2008) | 2 lines update release.py, clean up info.py: that data is misplaced ........ r881 | aric | 2008-11-01 12:42:20 -0600 (Sat, 01 Nov 2008) | 2 lines clean up doctests to pass with "import networkx as nx" ........ r882 | aric | 2008-11-01 13:08:07 -0600 (Sat, 01 Nov 2008) | 2 lines update doctests in readwrite/ ........ r883 | aric | 2008-11-01 13:15:08 -0600 (Sat, 01 Nov 2008) | 2 lines fix doctests in algorithms ........ r884 | aric | 2008-11-01 13:24:10 -0600 (Sat, 01 Nov 2008) | 8 lines fix remaining doctests - move bipartite.txt and threshold.txt out of the way for now nosetests --with-networkx-doctest --doctest-extension="txt" networkx passes all tests ........ r885 | aric | 2008-11-02 06:42:36 -0700 (Sun, 02 Nov 2008) | 2 lines clean up unused data, add test option to setup_egg ........ --HG-- extra : convert_revision : svn%3A3ed01bd8-26fb-0310-9e4c-ca1a4053419f/networkx/trunk%40887
Diffstat (limited to 'networkx/convert.py')
-rw-r--r--networkx/convert.py298
1 files changed, 141 insertions, 157 deletions
diff --git a/networkx/convert.py b/networkx/convert.py
index 5a5ff9a3..1b959834 100644
--- a/networkx/convert.py
+++ b/networkx/convert.py
@@ -1,28 +1,37 @@
"""
Convert NetworkX graphs to and from other formats.
-from_whatever attemps to guess the input format
+from_whatever attempts to guess the input format
-Create a 10 node random digraph
+Example: Create a 10 node random digraph
->>> from networkx import *
>>> import numpy
>>> a=numpy.reshape(numpy.random.random_integers(0,1,size=100),(10,10))
->>> D=from_whatever(a,create_using=DiGraph()) # or D=DiGraph(a)
+>>> D=nx.from_whatever(a,create_using=nx.DiGraph())
+
+or
+
+>>> D=nx.DiGraph(a)
For graphviz formats see networkx.drawing.nx_pygraphviz
or networkx.drawing.nx_pydot.
-$Id$
"""
__author__ = """Aric Hagberg (hagberg@lanl.gov)"""
-# Copyright (C) 2006 by
+# Copyright (C) 2006-2008 by
# Aric Hagberg <hagberg@lanl.gov>
# Dan Schult <dschult@colgate.edu>
# Pieter Swart <swart@lanl.gov>
# Distributed under the terms of the GNU Lesser General Public License
# http://www.gnu.org/copyleft/lesser.html
+
+__all__ = ['from_whatever',
+ 'from_dict_of_dicts', 'to_dict_of_dicts',
+ 'from_dict_of_lists', 'to_dict_of_lists',
+ 'from_numpy_matrix', 'to_numpy_matrix',
+ 'from_scipy_sparse_matrix', 'to_scipy_sparse_matrix']
+
import networkx
def _prep_create_using(create_using):
@@ -37,15 +46,15 @@ def _prep_create_using(create_using):
if create_using is None:
G=networkx.Graph()
else:
+ G=create_using
try:
- G=create_using
G.clear()
except:
raise TypeError("Input graph is not a networkx graph type")
return G
-def from_whatever(thing,create_using=None):
+def from_whatever(thing,create_using=None,multigraph_input=False):
"""Attempt to make a NetworkX graph from an known type.
Current known types are:
@@ -58,27 +67,37 @@ def from_whatever(thing,create_using=None):
scipy sparse matrix
pygraphviz agraph
+ If multigraph_input is True and thing is a dict_of_dicts,
+ try to create a multigraph assuming dict_of_dict_of_lists.
+ If thing and create_using are both multigraphs then create
+ a multigraph from a multigraph.
+
"""
- # pygraphviz agraph
- if hasattr(thing,"is_strict"):
+ # NX graph
+ if hasattr(thing,"adj"):
try:
- return networkx.from_agraph(thing,create_using=create_using)
+ result= from_dict_of_dicts(thing.adj,\
+ create_using=create_using,\
+ multigraph_input=thing.multigraph)
+ result.weighted=thing.weighted
+ return result
except:
raise networkx.NetworkXError,\
- "Input is not a correct pygraphviz graph."
+ "Input is not a correct NetworkX graph."
- # NX graph
- if hasattr(thing,"add_node"):
+ # pygraphviz agraph
+ if hasattr(thing,"is_strict"):
try:
- return from_dict_of_dicts(thing.adj,create_using=create_using)
+ return networkx.from_agraph(thing,create_using=create_using)
except:
raise networkx.NetworkXError,\
- "Input is not a correct NetworkX graph."
+ "Input is not a correct pygraphviz graph."
# dict of dicts/lists
if isinstance(thing,dict):
try:
- return from_dict_of_dicts(thing,create_using=create_using)
+ return from_dict_of_dicts(thing,create_using=create_using,\
+ multigraph_input=multigraph_input)
except:
try:
return from_dict_of_lists(thing,create_using=create_using)
@@ -123,7 +142,7 @@ def to_dict_of_lists(G,nodelist=None):
If nodelist is defined return a dict of lists with only those nodes.
- Completely ignores edge data for XGraph and XDiGraph.
+ Completely ignores edge data for MultiGraph and MultiDiGraph.
"""
if nodelist is None:
@@ -141,20 +160,19 @@ def from_dict_of_lists(d,create_using=None):
G=_prep_create_using(create_using)
G.add_nodes_from(d)
- if hasattr(G,"allow_multiedges") and G.multiedges and not G.is_directed():
+ if G.multigraph and not G.directed:
# a dict_of_lists can't show multiedges. BUT for undirected graphs,
# each edge shows up twice in the dict_of_lists.
# So we need to treat this case separately.
seen={}
- for node in d:
- for nbr in d[node]:
- if (node,nbr) not in seen:
+ for node,nbrlist in d.iteritems():
+ for nbr in nbrlist:
+ if nbr not in seen:
G.add_edge(node,nbr)
- seen[(nbr,node)]=1 # don't allow reverse edge to show up
+ seen[node]=1 # don't allow reverse edge to show up
else:
- for node in d:
- for nbr in d[node]:
- G.add_edge(node,nbr)
+ G.add_edges_from( ((node,nbr) for node,nbrlist in d.iteritems()
+ for nbr in nbrlist) )
return G
@@ -166,94 +184,83 @@ def to_dict_of_dicts(G,nodelist=None,edge_data=None):
If edge_data is given, the value of the dictionary will be
set to edge_data for all edges. This is useful to make
an adjacency matrix type representation with 1 as the edge data.
+ If edgedata is None, the edgedata in G is used to fill the values.
+ If G is a multigraph, the edgedata is a list for each pair (u,v).
"""
+ dod={}
if nodelist is None:
- nodelist=G.nodes()
- if edge_data is not None:
- get_edge=lambda x,y:edge_data
- else:
- get_edge=G.get_edge
-
- d = {}
- for u in nodelist:
- d[u]={}
- for v in G.neighbors(u):
- if v in nodelist:
- d[u][v]=get_edge(u,v)
- return d
-
-
-def from_dict_of_dicts(d,create_using=None):
+ if edge_data is None:
+ for u,nbrdict in G.adjacency_iter():
+ dod[u]=nbrdict.copy()
+ else: # edge_data is not None
+ for u,nbrdict in G.adjacency_iter():
+ dod[u]=dod.fromkeys(nbrdict, edge_data)
+ else: # nodelist is not None
+ if edge_data is None:
+ for u in nodelist:
+ dod[u]={}
+ for v,data in ((v,data) for v,data in G[u].iteritems() if v in nodelist):
+ dod[u][v]=data
+ else: # nodelist and edge_data are not None
+ for u in nodelist:
+ dod[u]={}
+ for v in ( v for v in G[u] if v in nodelist):
+ dod[u][v]=edge_data
+ return dod
+
+def from_dict_of_dicts(d,create_using=None,multigraph_input=False):
"""Return a NetworkX graph G from a Python dictionary of dictionaries.
- The value of the inner dict becomes the edge_data for the NetworkX graph
- EVEN if create_using is a NetworkX Graph which doesn't ever use this data.
+ The value of the inner dict becomes the edge_data for the NetworkX graph.
- If create_using is an XGraph/XDiGraph with multiedges==True, the edge_data
- should be a list, though this routine does not check for that.
+ When multigraph_input is True, the values of the inner dict are assumed
+ to be containers of edge data for multiple edges.
+ Otherwise this routine assumes the edgedata are singletons.
"""
G=_prep_create_using(create_using)
G.add_nodes_from(d)
- # is this a XGraph or XDiGraph?
- # FIXME
- # This is a bad way to check for whether edge data exists...
- # If someone ever creates a graph class with edge data and
- # without an allow_multiedges method, it won't work.
- if hasattr(G,'allow_multiedges'): # assume edge data
- if G.multiedges:
- # this is a NetworkX graph with multiedges=True
- # make a copy of the list of edge data (but not the edge data)
- if G.is_directed():
- for u,nbrs in d.iteritems():
- for v,datalist in nbrs.iteritems():
- if type(datalist) == type([]):
- dl=datalist[:] # copy of the edge_data list
- else:
- dl=[datalist]
- G.pred[u][v]=dl
- G.succ[u][v]=dl
- else:
- for u,nbrs in d.iteritems():
- for v,datalist in nbrs.iteritems():
- if type(datalist) == type([]):
- dl=datalist[:] # copy of the edge_data list
- else:
- dl=[datalist]
- G.adj[u][v]=dl
- G.adj[v][u]=dl
- else:
+ # is dict a MultiGraph or MultiDiGraph?
+ if multigraph_input:
+ # make a copy of the list of edge data (but not the edge data)
+ if G.directed: # copy edge list
+ G.add_edges_from( ((u,v,data) for u,nbrs in d.iteritems() \
+ for v,dl in nbrs.iteritems() for data in dl) )
+ else: # Undirected
+ seen={} # don't add both directions of undirected graph
+ for u,nbrs in d.iteritems():
+ for v,datalist in nbrs.iteritems():
+ if v not in seen:
+ G.add_edges_from( ((u,v,data) for data in datalist) )
+ seen[u]=1 # don't allow reverse edge to show up
+ else: # not a multigraph to multigraph transfer
+ if G.directed:
+ G.add_edges_from( ((u,v,data) for u,nbrs in d.iteritems() \
+ for v,data in nbrs.iteritems()) )
+ else: # need this if G is multigraph and slightly faster if not multigraph
+ seen={}
for u,nbrs in d.iteritems():
for v,data in nbrs.iteritems():
- G.add_edge(u,v,data)
- else: # no edge data
- for u,nbrs in d.iteritems():
- for v in nbrs:
- G.add_edge(u,v)
-
+ if v not in seen:
+ G.add_edge(u,v,data)
+ seen[u]=1
return G
-
def to_numpy_matrix(G,nodelist=None):
- """Return adjacency matrix of graph as a numpy matrix.
+ """Return the adjacency matrix of graph G as a numpy matrix.
If nodelist is defined return adjacency matrix with nodes in nodelist
- in the order specified. If not the ordering is whatever order
- the method G.nodes() produces.
+ in the order specified. All nodes must appear in nodelist or a KeyError
+ is raised.
+ If nodelist is None, the ordering is produced by G.nodes()
- For Graph/DiGraph types which have no edge data
- The value of the entry A[u,v] is one if there is an edge u-v
- and zero otherwise.
+ When G.weighted==False the value of the entry A[u,v] is one
+ if there is an edge u-v and zero otherwise.
- For XGraph/XDiGraph the edge data is assumed to be a weight and be
- able to be converted to a valid numpy type (e.g. an int or a
- float). The value of the entry A[u,v] is the weight given by
- get_edge(u,v) one if there is an edge u-v and zero otherwise.
-
- Graphs with multi-edges are not handled.
+ Multiple edges and edge data are both ignored for MultiGraph/MultiDiGraph.
"""
try:
@@ -262,36 +269,32 @@ def to_numpy_matrix(G,nodelist=None):
raise ImportError, \
"Import Error: not able to import numpy: http://numpy.scipy.org "
- if hasattr(G,"multiedges"):
- if G.multiedges:
- raise TypeError, \
- "Conversion to numpy_matrix not allowed with for graphs with multiedges."
if nodelist is None:
nodelist=G.nodes()
nlen=len(nodelist)
index=dict(zip(nodelist,range(nlen)))# dict mapping vertex name to position
A = numpy.asmatrix(numpy.zeros((nlen,nlen)))
- directed=G.is_directed()
- for e in G.edges_iter(nodelist):
- u=e[0]
- v=e[1]
- if len(e)==2:
- d=1
- else:
- d=e[2]
- if d is None: d=1 # None would be a nan in numpy, use 1
- if u not in nodelist or v not in nodelist:
- continue
- A[index[u],index[v]]=d
- if not directed:
- A[index[v],index[u]]=d
+ if G.weighted and not G.multigraph:
+ for n,nbrdict in G.adjacency_iter():
+ if n in index:
+ for nbr,data in nbrdict.iteritems():
+ if nbr in index:
+ A[index[n],index[nbr]]=data
+ else: # ignore edge data
+ for n,nbrdict in G.adjacency_iter():
+ if n in index:
+ for nbr in nbrdict:
+ if nbr in index:
+ A[index[n],index[nbr]]=1
return A
def from_numpy_matrix(A,create_using=None):
"""Return networkx graph G from numpy matrix adjacency list.
- >>> G=from_numpy_matrix(A)
+ >>> import numpy
+ >>> A=numpy.matrix([[1,1],[2,1]])
+ >>> G=nx.from_numpy_matrix(A)
"""
# This should never fail if you have created a numpy matrix with numpy...
@@ -313,17 +316,7 @@ def from_numpy_matrix(A,create_using=None):
# get a list of edges
x,y=numpy.asarray(A).nonzero()
- # is this a XGraph or XDiGraph?
- # FIXME
- # This is a bad way to check for whether edge data exists...
- # If someone ever creates a graph class with edge data and
- # without an allow_multiedges method, it won't work.
- if hasattr(G,'allow_multiedges'):
- for (u,v) in zip(x,y):
- G.add_edge(u,v,A[u,v])
- else:
- for (u,v) in zip(x,y):
- G.add_edge(u,v)
+ G.add_edges_from( ((u,v,A[u,v]) for (u,v) in zip(x,y)) )
return G
@@ -333,23 +326,17 @@ def to_scipy_sparse_matrix(G,nodelist=None):
Uses lil_matrix format. To convert to other formats see
scipy.sparse documentation.
- If nodelist is defined return adjacency matrix with nodes in nodelist
- in the order specified. If not the ordering is whatever order
- the method G.nodes() produces.
-
- For Graph/DiGraph types which have no edge data
- The value of the entry A[u,v] is one if there is an edge u-v
- and zero otherwise.
-
- For XGraph/XDiGraph the edge data is assumed to be a weight and be
- able to be converted to a valid numpy type (e.g. an int or a
- float). The value of the entry A[u,v] is the weight given by
- get_edge(u,v) one if there is an edge u-v and zero otherwise.
+ If nodelist is defined return adjacency matrix with nodes
+ in the order specified by nodelist. Otherwise the order
+ is produced by G.nodes().
- Graphs with multi-edges are not handled.
+ If G.weighted is True and G is not a multigraph, the edgedata
+ is assumed to be numeric and becomes the value of A[u.v].
+ Otherwise A[u,v] is one if an edge u-v exists and zero otherwise.
- >>> A=scipy_sparse_matrix(G)
- >>> A.tocsr() # convert to compressed row storage
+ >>> G=nx.path_graph(4)
+ >>> A=nx.to_scipy_sparse_matrix(G)
+ >>> C=A.tocsr() # convert to compressed row storage
"""
try:
@@ -359,29 +346,24 @@ def to_scipy_sparse_matrix(G,nodelist=None):
"""Import Error: not able to import scipy sparse:
see http://scipy.org"""
- if hasattr(G,"multiedges"):
- if G.multiedges:
- raise TypeError, \
- "Conversion to scipy_sparse_matrix not allowed with for graphs with multiedges."
if nodelist is None:
nodelist=G.nodes()
nlen=len(nodelist)
index=dict(zip(nodelist,range(nlen)))# dict mapping vertex name to position
A = sparse.lil_matrix((nlen,nlen))
- for e in G.edges_iter(nodelist):
- u=e[0]
- v=e[1]
- if len(e)==2:
- d=1
- else:
- d=e[2]
- if d is None: d=1 # None would be a nan, use 1
- if u not in nodelist or v not in nodelist:
- continue
- A[index[u],index[v]]=d
- if not G.is_directed():
- A[index[v],index[u]]=d
+ if G.weighted and not G.multigraph:
+ for n,nbrdict in G.adjacency_iter():
+ if n in index:
+ for nbr,data in nbrdict.iteritems():
+ if nbr in index:
+ A[index[n],index[nbr]]=data
+ else: # ignore edge data
+ for n,nbrdict in G.adjacency_iter():
+ if n in index:
+ for nbr in nbrdict:
+ if nbr in index:
+ A[index[n],index[nbr]]=1
return A
@@ -389,9 +371,12 @@ def from_scipy_sparse_matrix(A,create_using=None):
"""Return networkx graph G from scipy scipy sparse matrix
adjacency list.
- >>> G=from_scipy_sparse_matrix(A)
+ >>> import scipy.sparse
+ >>> A=scipy.sparse.eye(2,2,1)
+ >>> G=nx.from_scipy_sparse_matrix(A)
"""
+
G=_prep_create_using(create_using)
# is this a XGraph or XDiGraph?
@@ -423,7 +408,6 @@ def from_scipy_sparse_matrix(A,create_using=None):
G.add_edge(i,j)
return G
-
def _test_suite():
import doctest
suite = doctest.DocFileSuite('tests/convert.txt',