Source code for orbitsi.utils

"""Reading graph files (read_graph_from_file) and one-time start-up (warm_up)."""
import networkx as nx
from _orbitsi_core import read_graph

from .arraygraph import ArrayGraph
from .graphindex import GraphIndex


[docs] def read_graph_from_file(filepath, build_index=True): """Read a graph file into a NetworkX graph. The file is parsed in C++ straight into arrays (see :doc:`/file_format`). The result is an :class:`orbitsi.arraygraph.ArrayGraph`: a :class:`networkx.Graph` whose node and adjacency dictionaries are built only when first used. Parameters ---------- filepath : str or os.PathLike Path to the graph file. build_index : bool, default True Also build the graph's integer index (:class:`orbitsi.graphindex.GraphIndex`), its neighbour-label frequencies and the C++ core's copy (:func:`orbitsi.core.data_graph`), so that their cost is paid here and not by the first pattern searched; also runs :func:`warm_up` once per process. Returns ------- networkx.Graph The undirected graph, with each node's label in its ``'label'`` attribute. Raises ------ ValueError If a ``v`` or ``e`` line has a missing or non-integer field, or an integer outside 64 bits. """ with open(filepath, "rb") as f: data = f.read() G = ArrayGraph(arrays=read_graph(data)) del data if build_index: from .core import data_graph GraphIndex.of(G).nlf_table() data_graph(G) warm_up() return G
_warm = False
[docs] def warm_up(): """Pay one-time library start-up costs now. Runs filtering, ordering and counting once on a tiny graph with both backends, so that one-time start-up (NumPy's first sort sets up its SIMD dispatch, about 50 ms; the first calls of other array routines and of the C++ extensions) is paid at load, not by the first pattern. Does nothing after its first call in a process. """ global _warm if _warm: return _warm = True from .orbit import EVOKEOrbitCounter from .search import OrbitSIEngine G = nx.Graph([(0, 1), (1, 2), (2, 0), (2, 3), (3, 4), (4, 1)]) nx.set_node_attributes(G, {v: v % 2 for v in G.nodes}, "label") P = G.subgraph([0, 1, 2, 3]).copy() for backend in ("cpp", "python"): OrbitSIEngine(G, EVOKEOrbitCounter, order_method="core", backend=backend).count(P)