leda.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106
  1. """
  2. Read graphs in LEDA format.
  3. LEDA is a C++ class library for efficient data types and algorithms.
  4. Format
  5. ------
  6. See http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
  7. """
  8. # Original author: D. Eppstein, UC Irvine, August 12, 2003.
  9. # The original code at http://www.ics.uci.edu/~eppstein/PADS/ is public domain.
  10. __all__ = ["read_leda", "parse_leda"]
  11. import networkx as nx
  12. from networkx.exception import NetworkXError
  13. from networkx.utils import open_file
  14. @open_file(0, mode="rb")
  15. def read_leda(path, encoding="UTF-8"):
  16. """Read graph in LEDA format from path.
  17. Parameters
  18. ----------
  19. path : file or string
  20. File or filename to read. Filenames ending in .gz or .bz2 will be
  21. uncompressed.
  22. Returns
  23. -------
  24. G : NetworkX graph
  25. Examples
  26. --------
  27. G=nx.read_leda('file.leda')
  28. References
  29. ----------
  30. .. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
  31. """
  32. lines = (line.decode(encoding) for line in path)
  33. G = parse_leda(lines)
  34. return G
  35. def parse_leda(lines):
  36. """Read graph in LEDA format from string or iterable.
  37. Parameters
  38. ----------
  39. lines : string or iterable
  40. Data in LEDA format.
  41. Returns
  42. -------
  43. G : NetworkX graph
  44. Examples
  45. --------
  46. G=nx.parse_leda(string)
  47. References
  48. ----------
  49. .. [1] http://www.algorithmic-solutions.info/leda_guide/graphs/leda_native_graph_fileformat.html
  50. """
  51. if isinstance(lines, str):
  52. lines = iter(lines.split("\n"))
  53. lines = iter(
  54. [
  55. line.rstrip("\n")
  56. for line in lines
  57. if not (line.startswith(("#", "\n")) or line == "")
  58. ]
  59. )
  60. for i in range(3):
  61. next(lines)
  62. # Graph
  63. du = int(next(lines)) # -1=directed, -2=undirected
  64. if du == -1:
  65. G = nx.DiGraph()
  66. else:
  67. G = nx.Graph()
  68. # Nodes
  69. n = int(next(lines)) # number of nodes
  70. node = {}
  71. for i in range(1, n + 1): # LEDA counts from 1 to n
  72. symbol = next(lines).rstrip().strip("|{}| ")
  73. if symbol == "":
  74. symbol = str(i) # use int if no label - could be trouble
  75. node[i] = symbol
  76. G.add_nodes_from([s for i, s in node.items()])
  77. # Edges
  78. m = int(next(lines)) # number of edges
  79. for i in range(m):
  80. try:
  81. s, t, reversal, label = next(lines).split()
  82. except BaseException as err:
  83. raise NetworkXError(f"Too few fields in LEDA.GRAPH edge {i+1}") from err
  84. # BEWARE: no handling of reversal edges
  85. G.add_edge(node[int(s)], node[int(t)], label=label[2:-2])
  86. return G