You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

109 lines
2.7 KiB

5 months ago
"""
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")
@nx._dispatchable(graphs=None, returns_graph=True)
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
@nx._dispatchable(graphs=None, returns_graph=True)
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(("#", "\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 err:
raise NetworkXError(f"Too few fields in LEDA.GRAPH edge {i+1}") from err
# BEWARE: no handling of reversal edges
G.add_edge(node[int(s)], node[int(t)], label=label[2:-2])
return G