summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoraric <none@none>2010-08-20 20:21:28 +0000
committeraric <none@none>2010-08-20 20:21:28 +0000
commitc7af2b9dc774d5edd64fe0edc75ac6b291a60e4c (patch)
tree9d0c2e2da66df09822a95f50a5c42ba0b0d5a9fc
parente30ab2bc62b1e00d72daba88b78e75cd04fb3358 (diff)
downloadnetworkx-c7af2b9dc774d5edd64fe0edc75ac6b291a60e4c.tar.gz
Split multiline_adglist and adjlist. Add documentation.
Don't add linefeed to end of line in generate_* functions. --HG-- extra : convert_revision : svn%3A3ed01bd8-26fb-0310-9e4c-ca1a4053419f/networkx/trunk%401924
-rw-r--r--doc/source/reference/readwrite.adjlist.rst4
-rw-r--r--doc/source/reference/readwrite.rst1
-rw-r--r--networkx/readwrite/__init__.py2
-rw-r--r--networkx/readwrite/adjlist.py534
-rw-r--r--networkx/readwrite/multiline_adjlist.py389
5 files changed, 522 insertions, 408 deletions
diff --git a/doc/source/reference/readwrite.adjlist.rst b/doc/source/reference/readwrite.adjlist.rst
index 3550a109..cb86a364 100644
--- a/doc/source/reference/readwrite.adjlist.rst
+++ b/doc/source/reference/readwrite.adjlist.rst
@@ -10,5 +10,5 @@ Adjacency List
read_adjlist
write_adjlist
- read_multiline_adjlist
- write_multiline_adjlist
+ parse_adjlist
+ generate_adjlist
diff --git a/doc/source/reference/readwrite.rst b/doc/source/reference/readwrite.rst
index 37794d49..cde75d54 100644
--- a/doc/source/reference/readwrite.rst
+++ b/doc/source/reference/readwrite.rst
@@ -8,6 +8,7 @@ Reading and writing graphs
:maxdepth: 2
readwrite.adjlist
+ readwrite.multiline_adjlist
readwrite.edgelist
readwrite.gml
readwrite.gpickle
diff --git a/networkx/readwrite/__init__.py b/networkx/readwrite/__init__.py
index b4212251..2710e5c4 100644
--- a/networkx/readwrite/__init__.py
+++ b/networkx/readwrite/__init__.py
@@ -2,8 +2,8 @@
A package for reading and writing graphs in various formats.
"""
-import sys
from networkx.readwrite.adjlist import *
+from networkx.readwrite.multiline_adjlist import *
from networkx.readwrite.edgelist import *
from networkx.readwrite.gpickle import *
from networkx.readwrite.pajek import *
diff --git a/networkx/readwrite/adjlist.py b/networkx/readwrite/adjlist.py
index 05a9e29d..9712e725 100644
--- a/networkx/readwrite/adjlist.py
+++ b/networkx/readwrite/adjlist.py
@@ -1,396 +1,66 @@
# -*- coding: utf-8 -*-
"""
-***************
-Adjacency Lists
-***************
-
+**************
+Adjacency List
+**************
Read and write NetworkX graphs as adjacency lists.
-Note that NetworkX graphs can contain any hashable Python object as
-node (not just integers and strings). So writing a NetworkX graph
-as a text file may not always be what you want: see write_gpickle
-and gread_gpickle for that case.
-
-This module provides the following :
-
-Adjacency list with single line per node:
-Useful for connected or unconnected graphs without edge data.
+Adjacency list format is useful for graphs without data associated
+with nodes or edges and for nodes that can be meaningfully represented
+as strings.
->>> G=nx.path_graph(4)
->>> path='test.adjlist'
->>> write_adjlist(G, path)
->>> G=read_adjlist(path)
+Format
+------
+The adjacency list format consists of lines with node labels. The
+first label in a line is the source node. Further labels in the line
+are considered target nodes and are added to the graph along with an edge
+between the source node and target node.
-Adjacency list with multiple lines per node:
-Useful for connected or unconnected graphs with or without edge data.
-
->>> write_multiline_adjlist(G, path)
->>> G=read_multiline_adjlist(path)
+The graph with edges a-b, a-c, d-e can be represented as the following
+adjacency list (anything following the # in a line is a comment)::
+ a b c # source target target
+ d e
"""
__author__ = '\n'.join(['Aric Hagberg <hagberg@lanl.gov>',
'Dan Schult <dschult@colgate.edu>',
'Loïc Séguin-C. <loicseguin@gmail.com>'])
-# Copyright (C) 2004-2009 by
+# Copyright (C) 2004-2010 by
# Aric Hagberg <hagberg@lanl.gov>
# Dan Schult <dschult@colgate.edu>
# Pieter Swart <swart@lanl.gov>
# All rights reserved.
# BSD license.
-__all__ = ['generate_multiline_adjlist',
- 'write_multiline_adjlist',
- 'parse_multiline_adjlist',
- 'read_multiline_adjlist',
- 'generate_adjlist',
+__all__ = ['generate_adjlist',
'write_adjlist',
'parse_adjlist',
'read_adjlist']
-
from networkx.utils import is_string_like, make_str, _get_fh
import networkx as nx
-def generate_multiline_adjlist(G, delimiter = ' '):
- """Generate a single entry of the graph G in multiline adjacency list format.
-
- This function is a generator.
-
- See read_multiline_adjlist for format details.
-
- Examples
- --------
-
- >>> G = nx.lollipop_graph(4, 3)
- >>> adjlist_str = ''
- >>> for line in nx.generate_multiline_adjlist(G):
- ... adjlist_str += line
- ...
- >>> print(adjlist_str[:-1])
- 0 3
- 1 {}
- 2 {}
- 3 {}
- 1 2
- 2 {}
- 3 {}
- 2 1
- 3 {}
- 3 1
- 4 {}
- 4 1
- 5 {}
- 5 1
- 6 {}
- 6 0
-
- """
-
- if G.is_directed():
- if G.is_multigraph():
- for s,nbrs in G.adjacency_iter():
- nbr_edges=[ (u,data)
- for u,datadict in nbrs.items()
- for key,data in datadict.items()]
- deg=len(nbr_edges)
- multiline = make_str(s)+delimiter+"%i\n"%(deg)
- for u,d in nbr_edges:
- if d is None:
- multiline += make_str(u)+'\n'
- else:
- multiline += make_str(u)+delimiter+make_str(d)+"\n"
- yield multiline
- else: # directed single edges
- for s,nbrs in G.adjacency_iter():
- deg=len(nbrs)
- multiline = make_str(s)+delimiter+"%i\n"%(deg)
- for u,d in nbrs.items():
- if d is None:
- multiline += make_str(u)+'\n'
- else:
- multiline += make_str(u)+delimiter+make_str(d)+"\n"
- yield multiline
- else: # undirected
- if G.is_multigraph():
- seen=set() # helper dict used to avoid duplicate edges
- for s,nbrs in G.adjacency_iter():
- nbr_edges=[ (u,data)
- for u,datadict in nbrs.items()
- if u not in seen
- for key,data in datadict.items()]
- deg=len(nbr_edges)
- multiline = make_str(s)+delimiter+"%i\n"%(deg)
- for u,d in nbr_edges:
- if d is None:
- multiline += make_str(u)+'\n'
- else:
- multiline += make_str(u)+delimiter+make_str(d)+"\n"
- seen.add(s)
- yield multiline
- else: # undirected single edges
- seen=set() # helper dict used to avoid duplicate edges
- for s,nbrs in G.adjacency_iter():
- nbr_edges=[ (u,d) for u,d in nbrs.items() if u not in seen]
- deg=len(nbr_edges)
- multiline = make_str(s)+delimiter+"%i\n"%(deg)
- for u,d in nbr_edges:
- if d is None:
- multiline += make_str(u)+'\n'
- else:
- multiline += make_str(u)+delimiter+make_str(d)+"\n"
- seen.add(s)
- yield multiline
-
-def write_multiline_adjlist(G, path, delimiter=' ', comments='#',
- encoding = 'utf-8'):
- """
- Write the graph G in multiline adjacency list format to the file or file handle path.
-
- See read_multiline_adjlist for file format details.
-
- Examples
- --------
-
- >>> G=nx.path_graph(4)
- >>> nx.write_multiline_adjlist(G,"test.adjlist")
-
- path can be a filehandle or a string with the name of the file. If a
- filehandle is provided, it has to be opened in 'wb' mode.
-
- >>> fh=open("test.adjlist",'wb')
- >>> nx.write_multiline_adjlist(G,fh)
-
- Filenames ending in .gz or .bz2 will be compressed.
-
- >>> nx.write_multiline_adjlist(G,"test.adjlist.gz")
-
- The file will use the utf-8 encoding by default.
- It is possible to write files in other encodings by providing the
- encoding argument to write_multiline_adjlist.
-
- >>> fh=open("test.adjlist",'wb')
- >>> nx.write_multiline_adjlist(G,fh,encoding='utf-8')
-
- The same result can be obtained with the following call.
- >>> nx.write_multiline_adjlist(G, 'test-utf8.adjlist', encoding = 'utf-8')
-
- """
- import sys
- import time
-
- fh=_get_fh(path,mode='wb')
- pargs=comments+" ".join(sys.argv)
- header = ("%s\n" % (pargs)
- + comments + " GMT %s\n" % (time.asctime(time.gmtime()))
- + comments + " %s\n" % (G.name))
- fh.write(header.encode(encoding))
-
- for multiline in generate_multiline_adjlist(G, delimiter):
- fh.write(multiline.encode(encoding))
-
-def parse_multiline_adjlist(lines, comments = '#', delimiter = ' ',
- create_using = None, nodetype = None,
- edgetype = None):
- """Parse lines of a multiline adjacency list representation of a graph.
-
- See read_multiline_adjlist for file format details.
-
- Returns
- -------
- G: NetworkX Graph
- The graph corresponding to lines
-
- Examples
- --------
- >>> lines = ['1 2',
- ... "2 {'weight':3, 'name': 'Frodo'}",
- ... "3 {}",
- ... "2 1",
- ... "5 {'weigth':6, 'name': 'Saruman'}"]
- >>> G = nx.parse_multiline_adjlist(iter(lines), nodetype = int)
- >>> G.nodes()
- [1, 2, 3, 5]
- >>> G.edges(data = True)
- [(1, 2, {'name': 'Frodo', 'weight': 3}), (1, 3, {}), (2, 5, {'name': 'Saruman', 'weigth': 6})]
-
-
- """
- if create_using is None:
- G=nx.Graph()
- else:
- try:
- G=create_using
- G.clear()
- except:
- raise TypeError("Input graph is not a networkx graph type")
-
- for line in lines:
- p=line.find(comments)
- if p>=0:
- line = line[:p]
- if not line: continue
- try:
- (u,deg)=line.strip().split(delimiter)
- deg=int(deg)
- except:
- raise TypeError("Failed to read node and degree on line (%s)"%line)
- if nodetype is not None:
- try:
- u=nodetype(u)
- except:
- raise TypeError("Failed to convert node (%s) to type %s"\
- %(u,nodetype))
- G.add_node(u)
- for i in range(deg):
- while True:
- try:
- line = next(lines)
- except StopIteration:
- msg = "Failed to find neighbor for node (%s)" % (u,)
- raise TypeError(msg)
- p=line.find(comments)
- if p>=0:
- line = line[:p]
- if line: break
- vlist=line.strip().split(delimiter)
- numb=len(vlist)
- if numb<1:
- continue # isolated node
- v=vlist.pop(0)
- data=''.join(vlist)
- if nodetype is not None:
- try:
- v=nodetype(v)
- except:
- raise TypeError(
- "Failed to convert node (%s) to type %s"\
- %(v,nodetype))
- if edgetype is not None:
- try:
- edgedata={'weight':edgetype(data)}
- except:
- raise TypeError(
- "Failed to convert edge data (%s) to type %s"\
- %(data, edgetype))
- else:
- try:
- from ast import literal_eval
- except:
- literal_eval=eval # use potentially unsafe built-in eval
- try: # try to evaluate
- edgedata=literal_eval(data)
- except:
- edgedata={}
- G.add_edge(u,v,attr_dict=edgedata)
-
- return G
-
-
-def read_multiline_adjlist(path, comments="#", delimiter=' ',
- create_using=None,
- nodetype=None, edgetype=None,
- encoding = 'utf-8'):
- """Read graph in multi-line adjacency list format from path.
-
- Examples
- --------
-
- >>> G=nx.path_graph(4)
- >>> nx.write_multiline_adjlist(G,"test.adjlist")
- >>> G=nx.read_multiline_adjlist("test.adjlist")
-
- path can be a filehandle or a string with the name of the file. If a
- filehandle is provided, it has to be opened in 'rb' mode.
-
- >>> fh=open("test.adjlist", 'rb')
- >>> G=nx.read_multiline_adjlist(fh)
-
- Filenames ending in .gz or .bz2 will be compressed.
-
- >>> nx.write_multiline_adjlist(G,"test.adjlist.gz")
- >>> G=nx.read_multiline_adjlist("test.adjlist.gz")
-
- nodetype is an optional function to convert node strings to nodetype
-
- For example
-
- >>> G=nx.read_multiline_adjlist("test.adjlist", nodetype=int)
-
- will attempt to convert all nodes to integer type
-
- Since nodes must be hashable, the function nodetype must return hashable
- types (e.g. int, float, str, frozenset - or tuples of those, etc.)
-
- edgetype is a function to convert edge data strings to edgetype
-
- >>> G=nx.read_multiline_adjlist("test.adjlist")
-
- create_using is an optional networkx graph type, the default is
- Graph(), a simple undirected graph
-
- >>> G=nx.read_multiline_adjlist("test.adjlist", create_using=nx.DiGraph())
-
- The comments character (default='#') at the beginning of a
- line indicates a comment line.
-
- The entries are separated by delimiter (default=' ').
- If whitespace is significant in node or edge labels you should use
- some other delimiter such as a tab or other symbol.
-
-
- Example multiline adjlist file format
-
- No edge data::
-
- # source target for Graph or DiGraph
- a 2
- b
- c
- d 1
- e
-
- With edge data::
-
- # source target for XGraph or XDiGraph with edge data
- a 2
- b edge-ab-data
- c edge-ac-data
- d 1
- e edge-de-data
-
- Reading the file will use the utf-8 text encoding by default.
- It is possible to read files with other encodings by providing the
- encoding arguement to read_multiline_adjlist.
-
- >>> fh=open("test.adjlist",'rb')
- >>> G=nx.read_multiline_adjlist(fh, encoding = 'iso-8859-1')
- """
- inp=_get_fh(path, 'rb')
- lines = (line.decode(encoding) for line in inp)
- return parse_multiline_adjlist(lines,
- comments = comments,
- delimiter = delimiter,
- create_using = create_using,
- nodetype = nodetype,
- edgetype = edgetype)
-
def generate_adjlist(G, delimiter = ' '):
"""Generate a single line of the graph G in adjacency list format.
- This function is a generator.
+ Parameters
+ ----------
+ G : NetworkX graph
+
+ delimiter : string, optional
+ Separator for node labels
- See read_adjlist for line format details.
+ Yields
+ ------
+ lines : string
+ Lines of data in adjlist format.
Examples
--------
-
>>> G = nx.lollipop_graph(4, 3)
- >>> adjlist_str = ''
>>> for line in nx.generate_adjlist(G):
- ... adjlist_str += line
- ...
- >>> print(adjlist_str[:-1])
+ ... print(line)
0 1 2 3
1 2 3
2 3
@@ -399,6 +69,10 @@ def generate_adjlist(G, delimiter = ' '):
5 6
6
+ See Also
+ --------
+ write_adjlist, read_adjlist
+
"""
directed=G.is_directed()
seen=set()
@@ -412,7 +86,6 @@ def generate_adjlist(G, delimiter = ' '):
line += make_str(t) + delimiter
else:
line += make_str(t) + delimiter
- line += '\n'
if not directed:
seen.add(s)
yield line
@@ -421,33 +94,42 @@ def generate_adjlist(G, delimiter = ' '):
def write_adjlist(G, path, comments="#", delimiter=' ', encoding = 'utf-8'):
"""Write graph G in single-line adjacency-list format to path.
- See read_adjlist for file format details.
+
+ Parameters
+ ----------
+ G : NetworkX graph
+
+ path : string or file
+ Filename or file handle for data output.
+ Filenames ending in .gz or .bz2 will be compressed.
+
+ comments : string, optional
+ Marker for comment lines
+
+ delimiter : string, optional
+ Separator for node labels
+
+ encoding : string, optional
+ Text encoding.
Examples
--------
-
>>> G=nx.path_graph(4)
>>> nx.write_adjlist(G,"test.adjlist")
- path can be a filehandle or a string with the name of the file. If a
+ The path can be a filehandle or a string with the name of the file. If a
filehandle is provided, it has to be opened in 'wb' mode.
>>> fh=open("test.adjlist",'wb')
>>> nx.write_adjlist(G, fh)
- Filenames ending in .gz or .bz2 will be compressed.
-
- >>> nx.write_adjlist(G, "test.adjlist.gz")
+ Notes
+ -----
+ This format does not store graph, node, or edge data.
- The file will use the utf-8 encoding by default.
- It is possible to write files in other encodings by providing the
- encoding argument to write_adjlist.
-
- >>> fh=open("test.adjlist", 'wb')
- >>> nx.write_adjlist(G,fh, encoding='iso-8859-1')
-
- Does not handle edge data.
- Use 'write_edgelist' or 'write_multiline_adjlist'
+ See Also
+ --------
+ read_adjlist, generate_adjlist
"""
import sys
import time
@@ -459,18 +141,38 @@ def write_adjlist(G, path, comments="#", delimiter=' ', encoding = 'utf-8'):
fh.write(header.encode(encoding))
for line in generate_adjlist(G, delimiter):
+ line+='\n'
fh.write(line.encode(encoding))
def parse_adjlist(lines, comments = '#', delimiter = ' ',
create_using = None, nodetype = None):
- """Parse lines of an adjacency list representation of a graph.
+ """Parse lines of a graph adjacency list representation.
+
+ Parameters
+ ----------
+ lines : list or iterator of strings
+ Input data in adjlist format
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
+
+ nodetype : Python type, optional
+ Convert nodes to this type.
+
+ comments : string, optional
+ Marker for comment lines
+
+ delimiter : string, optional
+ Separator for node labels
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
- See read_adjlist for file format details.
Returns
-------
- G: NetworkX Graph
+ G: NetworkX graph
The graph corresponding to the lines in adjacency list format.
Examples
@@ -480,11 +182,15 @@ def parse_adjlist(lines, comments = '#', delimiter = ' ',
... '3 5',
... '4',
... '5']
- >>> G = nx.parse_adjlist(iter(lines), nodetype = int)
+ >>> G = nx.parse_adjlist(lines, nodetype = int)
>>> G.nodes()
[1, 2, 3, 4, 5]
>>> G.edges()
[(1, 2), (1, 5), (2, 3), (2, 4), (3, 5)]
+
+ See Also
+ --------
+ read_adjlist
"""
if create_using is None:
@@ -494,7 +200,7 @@ def parse_adjlist(lines, comments = '#', delimiter = ' ',
G=create_using
G.clear()
except:
- raise TypeError("Input graph is not a networkx graph type")
+ raise TypeError("Input graph is not a NetworkX graph type")
for line in lines:
p=line.find(comments)
@@ -521,19 +227,44 @@ def parse_adjlist(lines, comments = '#', delimiter = ' ',
G.add_edges_from([(u, v) for v in vlist])
return G
-def read_adjlist(path, comments="#", delimiter=' ',
- create_using=None, nodetype=None,
- encoding = 'utf-8'):
- """Read graph in single line adjacency list format from path.
+def read_adjlist(path, comments="#", delimiter=' ', create_using=None,
+ nodetype=None, encoding = 'utf-8'):
+ """Read graph in adjacency list format from path.
+
+ Parameters
+ ----------
+ path : string or file
+ Filename or file handle to read.
+ Filenames ending in .gz or .bz2 will be uncompressed.
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
+
+ nodetype : Python type, optional
+ Convert nodes to this type.
+
+ comments : string, optional
+ Marker for comment lines
+
+ delimiter : string, optional
+ Separator for node labels
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
+
+
+ Returns
+ -------
+ G: NetworkX graph
+ The graph corresponding to the lines in adjacency list format.
Examples
--------
-
>>> G=nx.path_graph(4)
>>> nx.write_adjlist(G, "test.adjlist")
>>> G=nx.read_adjlist("test.adjlist")
- path can be a filehandle or a string with the name of the file. If a
+ The path can be a filehandle or a string with the name of the file. If a
filehandle is provided, it has to be opened in 'rb' mode.
>>> fh=open("test.adjlist", 'rb')
@@ -541,40 +272,33 @@ def read_adjlist(path, comments="#", delimiter=' ',
Filenames ending in .gz or .bz2 will be compressed.
- >>> nx.write_adjlist(G, "test.adjlist.gz")
+ >>> nx.write_adjlist(G,"test.adjlist.gz")
>>> G=nx.read_adjlist("test.adjlist.gz")
- nodetype is an optional function to convert node strings to nodetype
+ The optional nodetype is a function to convert node strings to nodetype.
For example
>>> G=nx.read_adjlist("test.adjlist", nodetype=int)
- will attempt to convert all nodes to integer type
+ will attempt to convert all nodes to integer type.
Since nodes must be hashable, the function nodetype must return hashable
types (e.g. int, float, str, frozenset - or tuples of those, etc.)
- create_using is an optional networkx graph type, the default is
- Graph(), an undirected graph.
+ The optional create_using parameter is a NetworkX graph container.
+ The default is Graph(), an undirected graph. To read the data as
+ a directed graph use
>>> G=nx.read_adjlist("test.adjlist", create_using=nx.DiGraph())
- Does not handle edge data: use 'read_edgelist' or 'read_multiline_adjlist'
-
- The comments character (default='#') at the beginning of a
- line indicates a comment line.
-
- The entries are separated by delimiter (default=' ').
- If whitespace is significant in node or edge labels you should use
- some other delimiter such as a tab or other symbol.
-
- Sample format::
-
- # source target
- a b c
- d e
+ Notes
+ -----
+ This format does not store graph or node data.
+ See Also
+ --------
+ write_adjlist
"""
fh=_get_fh(path, 'rb')
lines = (line.decode(encoding) for line in fh)
diff --git a/networkx/readwrite/multiline_adjlist.py b/networkx/readwrite/multiline_adjlist.py
new file mode 100644
index 00000000..7c56facd
--- /dev/null
+++ b/networkx/readwrite/multiline_adjlist.py
@@ -0,0 +1,389 @@
+# -*- coding: utf-8 -*-
+"""
+*************************
+Multi-line Adjacency List
+*************************
+Read and write NetworkX graphs as multi-line adjacency lists.
+
+The multi-line adjacency list format is useful for graphs with
+nodes that can be meaningfully represented as strings. With this format
+simple edge data can be stored but node or graph data is not.
+
+Format
+------
+The first label in a line is the source node label followed by the node degree
+d. The next d lines are target node labels and optional edge data.
+That pattern repeats for all nodes in the graph.
+
+The graph with edges a-b, a-c, d-e can be represented as the following
+adjacency list (anything following the # in a line is a comment)::
+
+ # example.multiline-adjlist
+ a 2
+ b
+ c
+ d 1
+ e
+"""
+__author__ = '\n'.join(['Aric Hagberg <hagberg@lanl.gov>',
+ 'Dan Schult <dschult@colgate.edu>',
+ 'Loïc Séguin-C. <loicseguin@gmail.com>'])
+# Copyright (C) 2004-2010 by
+# Aric Hagberg <hagberg@lanl.gov>
+# Dan Schult <dschult@colgate.edu>
+# Pieter Swart <swart@lanl.gov>
+# All rights reserved.
+# BSD license.
+
+__all__ = ['generate_multiline_adjlist',
+ 'write_multiline_adjlist',
+ 'parse_multiline_adjlist',
+ 'read_multiline_adjlist']
+
+from networkx.utils import is_string_like, make_str, _get_fh
+import networkx as nx
+
+def generate_multiline_adjlist(G, delimiter = ' '):
+ """Generate a single line of the graph G in multiline adjacency list format.
+
+ Parameters
+ ----------
+ G : NetworkX graph
+
+ delimiter : string, optional
+ Separator for node labels
+
+ Yields
+ ------
+ lines : string
+ Lines of data in multiline adjlist format.
+
+ Examples
+ --------
+ >>> G = nx.lollipop_graph(4, 3)
+ >>> for line in nx.generate_multiline_adjlist(G):
+ ... print(line)
+ 0 3
+ 1 {}
+ 2 {}
+ 3 {}
+ 1 2
+ 2 {}
+ 3 {}
+ 2 1
+ 3 {}
+ 3 1
+ 4 {}
+ 4 1
+ 5 {}
+ 5 1
+ 6 {}
+ 6 0
+
+ See Also
+ --------
+ write_multiline_adjlist, read_multiline_adjlist
+ """
+ if G.is_directed():
+ if G.is_multigraph():
+ for s,nbrs in G.adjacency_iter():
+ nbr_edges=[ (u,data)
+ for u,datadict in nbrs.items()
+ for key,data in datadict.items()]
+ deg=len(nbr_edges)
+ yield make_str(s)+delimiter+"%i"%(deg)
+ for u,d in nbr_edges:
+ if d is None:
+ yield make_str(u)
+ else:
+ yield make_str(u)+delimiter+make_str(d)
+ else: # directed single edges
+ for s,nbrs in G.adjacency_iter():
+ deg=len(nbrs)
+ yield make_str(s)+delimiter+"%i"%(deg)
+ for u,d in nbrs.items():
+ if d is None:
+ yield make_str(u)
+ else:
+ yield make_str(u)+delimiter+make_str(d)
+ else: # undirected
+ if G.is_multigraph():
+ seen=set() # helper dict used to avoid duplicate edges
+ for s,nbrs in G.adjacency_iter():
+ nbr_edges=[ (u,data)
+ for u,datadict in nbrs.items()
+ if u not in seen
+ for key,data in datadict.items()]
+ deg=len(nbr_edges)
+ yield make_str(s)+delimiter+"%i"%(deg)
+ for u,d in nbr_edges:
+ if d is None:
+ yield make_str(u)
+ else:
+ yield make_str(u)+delimiter+make_str(d)
+ seen.add(s)
+ else: # undirected single edges
+ seen=set() # helper dict used to avoid duplicate edges
+ for s,nbrs in G.adjacency_iter():
+ nbr_edges=[ (u,d) for u,d in nbrs.items() if u not in seen]
+ deg=len(nbr_edges)
+ yield make_str(s)+delimiter+"%i"%(deg)
+ for u,d in nbr_edges:
+ if d is None:
+ yield make_str(u)
+ else:
+ yield make_str(u)+delimiter+make_str(d)
+ seen.add(s)
+
+def write_multiline_adjlist(G, path, delimiter=' ',
+ comments='#', encoding = 'utf-8'):
+ """ Write the graph G in multiline adjacency list format to path
+
+ Parameters
+ ----------
+ G : NetworkX graph
+
+ comments : string, optional
+ Marker for comment lines
+
+ delimiter : string, optional
+ Separator for node labels
+
+ encoding : string, optional
+ Text encoding.
+
+ Examples
+ --------
+ >>> G=nx.path_graph(4)
+ >>> nx.write_multiline_adjlist(G,"test.adjlist")
+
+ The path can be a file handle or a string with the name of the file. If a
+ file handle is provided, it has to be opened in 'wb' mode.
+
+ >>> fh=open("test.adjlist",'wb')
+ >>> nx.write_multiline_adjlist(G,fh)
+
+ Filenames ending in .gz or .bz2 will be compressed.
+
+ >>> nx.write_multiline_adjlist(G,"test.adjlist.gz")
+
+ See Also
+ --------
+ read_multiline_adjlist
+ """
+ import sys
+ import time
+
+ fh=_get_fh(path,mode='wb')
+ pargs=comments+" ".join(sys.argv)
+ header = ("%s\n" % (pargs)
+ + comments + " GMT %s\n" % (time.asctime(time.gmtime()))
+ + comments + " %s\n" % (G.name))
+ fh.write(header.encode(encoding))
+
+ for multiline in generate_multiline_adjlist(G, delimiter):
+ multiline+='\n'
+ fh.write(multiline.encode(encoding))
+
+def parse_multiline_adjlist(lines, comments = '#', delimiter = ' ',
+ create_using = None, nodetype = None,
+ edgetype = None):
+ """Parse lines of a multiline adjacency list representation of a graph.
+
+ Parameters
+ ----------
+ lines : list or iterator of strings
+ Input data in multiline adjlist format
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
+
+ nodetype : Python type, optional
+ Convert nodes to this type.
+
+ comments : string, optional
+ Marker for comment lines
+
+ delimiter : string, optional
+ Separator for node labels
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
+
+
+ Returns
+ -------
+ G: NetworkX graph
+ The graph corresponding to the lines in multiline adjacency list format.
+
+ Examples
+ --------
+ >>> lines = ['1 2',
+ ... "2 {'weight':3, 'name': 'Frodo'}",
+ ... "3 {}",
+ ... "2 1",
+ ... "5 {'weight':6, 'name': 'Saruman'}"]
+ >>> G = nx.parse_multiline_adjlist(iter(lines), nodetype = int)
+ >>> G.nodes()
+ [1, 2, 3, 5]
+ >>> G.edges(data = True)
+ [(1, 2, {'name': 'Frodo', 'weight': 3}), (1, 3, {}), (2, 5, {'name': 'Saruman', 'weight': 6})]
+
+ """
+ from ast import literal_eval
+ if create_using is None:
+ G=nx.Graph()
+ else:
+ try:
+ G=create_using
+ G.clear()
+ except:
+ raise TypeError("Input graph is not a networkx graph type")
+
+ for line in lines:
+ p=line.find(comments)
+ if p>=0:
+ line = line[:p]
+ if not line: continue
+ try:
+ (u,deg)=line.strip().split(delimiter)
+ deg=int(deg)
+ except:
+ raise TypeError("Failed to read node and degree on line (%s)"%line)
+ if nodetype is not None:
+ try:
+ u=nodetype(u)
+ except:
+ raise TypeError("Failed to convert node (%s) to type %s"\
+ %(u,nodetype))
+ G.add_node(u)
+ for i in range(deg):
+ while True:
+ try:
+ line = next(lines)
+ except StopIteration:
+ msg = "Failed to find neighbor for node (%s)" % (u,)
+ raise TypeError(msg)
+ p=line.find(comments)
+ if p>=0:
+ line = line[:p]
+ if line: break
+ vlist=line.strip().split(delimiter)
+ numb=len(vlist)
+ if numb<1:
+ continue # isolated node
+ v=vlist.pop(0)
+ data=''.join(vlist)
+ if nodetype is not None:
+ try:
+ v=nodetype(v)
+ except:
+ raise TypeError(
+ "Failed to convert node (%s) to type %s"\
+ %(v,nodetype))
+ if edgetype is not None:
+ try:
+ edgedata={'weight':edgetype(data)}
+ except:
+ raise TypeError(
+ "Failed to convert edge data (%s) to type %s"\
+ %(data, edgetype))
+ else:
+ try: # try to evaluate
+ edgedata=literal_eval(data)
+ except:
+ edgedata={}
+ G.add_edge(u,v,attr_dict=edgedata)
+
+ return G
+
+
+def read_multiline_adjlist(path, comments="#", delimiter=' ',
+ create_using=None,
+ nodetype=None, edgetype=None,
+ encoding = 'utf-8'):
+ """Read graph in multi-line adjacency list format from path.
+
+ Parameters
+ ----------
+ path : string or file
+ Filename or file handle to read.
+ Filenames ending in .gz or .bz2 will be uncompressed.
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
+
+ nodetype : Python type, optional
+ Convert nodes to this type.
+
+ edgetype : Python type, optional
+ Convert edge data to this type.
+
+ comments : string, optional
+ Marker for comment lines
+
+ delimiter : string, optional
+ Separator for node labels
+
+ create_using: NetworkX graph container
+ Use given NetworkX graph for holding nodes or edges.
+
+
+ Returns
+ -------
+ G: NetworkX graph
+
+ Examples
+ --------
+ >>> G=nx.path_graph(4)
+ >>> nx.write_multiline_adjlist(G,"test.adjlist")
+ >>> G=nx.read_multiline_adjlist("test.adjlist")
+
+ The path can be a file or a string with the name of the file. If a
+ file s provided, it has to be opened in 'rb' mode.
+
+ >>> fh=open("test.adjlist", 'rb')
+ >>> G=nx.read_multiline_adjlist(fh)
+
+ Filenames ending in .gz or .bz2 will be compressed.
+
+ >>> nx.write_multiline_adjlist(G,"test.adjlist.gz")
+ >>> G=nx.read_multiline_adjlist("test.adjlist.gz")
+
+ The optional nodetype is a function to convert node strings to nodetype.
+
+ For example
+
+ >>> G=nx.read_multiline_adjlist("test.adjlist", nodetype=int)
+
+ will attempt to convert all nodes to integer type.
+
+ The optional edgetype is a function to convert edge data strings to
+ edgetype.
+
+ >>> G=nx.read_multiline_adjlist("test.adjlist")
+
+ The optional create_using parameter is a NetworkX graph container.
+ The default is Graph(), an undirected graph. To read the data as
+ a directed graph use
+
+ >>> G=nx.read_multiline_adjlist("test.adjlist", create_using=nx.DiGraph())
+
+ Notes
+ -----
+ This format does not store graph, node, or edge data.
+
+ See Also
+ --------
+ write_multiline_adjlist
+ """
+ inp=_get_fh(path, 'rb')
+ lines = (line.decode(encoding) for line in inp)
+ return parse_multiline_adjlist(lines,
+ comments = comments,
+ delimiter = delimiter,
+ create_using = create_using,
+ nodetype = nodetype,
+ edgetype = edgetype)
+
+