107 lines
2.6 KiB
Python
107 lines
2.6 KiB
Python
|
"""
|
||
|
Read graphs in LEDA format.
|
||
|
|
||
|
LEDA is a C++ class library for efficient data types and algorithms.
|
||
|
|
||
|
Format
|
||
|
------
|
||
|
See http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
|
||
|
|
||
|
"""
|
||
|
# Original author: D. Eppstein, UC Irvine, August 12, 2003.
|
||
|
# The original code at http://www.ics.uci.edu/~eppstein/PADS/ is public domain.
|
||
|
|
||
|
__all__ = ["read_leda", "parse_leda"]
|
||
|
|
||
|
import networkx as nx
|
||
|
from networkx.exception import NetworkXError
|
||
|
from networkx.utils import open_file
|
||
|
|
||
|
|
||
|
@open_file(0, mode="rb")
|
||
|
def read_leda(path, encoding="UTF-8"):
|
||
|
"""Read graph in LEDA format from path.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
path : file or string
|
||
|
File or filename to read. Filenames ending in .gz or .bz2 will be
|
||
|
uncompressed.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
G : NetworkX graph
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
G=nx.read_leda('file.leda')
|
||
|
|
||
|
References
|
||
|
----------
|
||
|
.. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
|
||
|
"""
|
||
|
lines = (line.decode(encoding) for line in path)
|
||
|
G = parse_leda(lines)
|
||
|
return G
|
||
|
|
||
|
|
||
|
def parse_leda(lines):
|
||
|
"""Read graph in LEDA format from string or iterable.
|
||
|
|
||
|
Parameters
|
||
|
----------
|
||
|
lines : string or iterable
|
||
|
Data in LEDA format.
|
||
|
|
||
|
Returns
|
||
|
-------
|
||
|
G : NetworkX graph
|
||
|
|
||
|
Examples
|
||
|
--------
|
||
|
G=nx.parse_leda(string)
|
||
|
|
||
|
References
|
||
|
----------
|
||
|
.. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
|
||
|
"""
|
||
|
if isinstance(lines, str):
|
||
|
lines = iter(lines.split("\n"))
|
||
|
lines = iter(
|
||
|
[
|
||
|
line.rstrip("\n")
|
||
|
for line in lines
|
||
|
if not (line.startswith("#") or line.startswith("\n") or line == "")
|
||
|
]
|
||
|
)
|
||
|
for i in range(3):
|
||
|
next(lines)
|
||
|
# Graph
|
||
|
du = int(next(lines)) # -1=directed, -2=undirected
|
||
|
if du == -1:
|
||
|
G = nx.DiGraph()
|
||
|
else:
|
||
|
G = nx.Graph()
|
||
|
|
||
|
# Nodes
|
||
|
n = int(next(lines)) # number of nodes
|
||
|
node = {}
|
||
|
for i in range(1, n + 1): # LEDA counts from 1 to n
|
||
|
symbol = next(lines).rstrip().strip("|{}| ")
|
||
|
if symbol == "":
|
||
|
symbol = str(i) # use int if no label - could be trouble
|
||
|
node[i] = symbol
|
||
|
|
||
|
G.add_nodes_from([s for i, s in node.items()])
|
||
|
|
||
|
# Edges
|
||
|
m = int(next(lines)) # number of edges
|
||
|
for i in range(m):
|
||
|
try:
|
||
|
s, t, reversal, label = next(lines).split()
|
||
|
except BaseException as e:
|
||
|
raise NetworkXError(f"Too few fields in LEDA.GRAPH edge {i+1}") from e
|
||
|
# BEWARE: no handling of reversal edges
|
||
|
G.add_edge(node[int(s)], node[int(t)], label=label[2:-2])
|
||
|
return G
|