Skip to content

Integrations

graphfinder.integrations bridges graphfinder's search to popular libraries. Each integration is an optional extra and imports its dependency lazily — so importing graphfinder pulls in none of them:

pip install "graphfinder[networkx]"   # search over networkx graphs
pip install "graphfinder[scipy]"      # search over scipy.sparse adjacency
pip install "graphfinder[pandas]"     # edge-list DataFrames + result tables
pip install "graphfinder[osm]"        # route on real road networks (OSMnx)
pip install "graphfinder[agents]"     # LangChain routing tool
pip install "graphfinder[gym]"        # GridWorld RL environment + A* oracle
pip install "graphfinder[graphviz]"   # export graphs/paths to DOT/SVG

Every search helper returns a LabeledResult: the path is mapped back to your original node labels, while the native SearchResult stays in .raw (for metrics and graphfinder.viz).

r.path            # ["A", "B", "C", ...]  (your labels)
r.cost, r.found, r.nodes_expanded, r.stop_reason
r.raw             # native SearchResult (integer-id path/trace, for viz)

NetworkX

A drop-in alternative to nx.shortest_path / nx.astar_path that also reports search instrumentation (nodes expanded, frontier peak, trace). Directed graphs are honoured automatically; edge weights come from the weight attribute.

import networkx as nx
from graphfinder.integrations import networkx as gfnx

g = nx.Graph()
g.add_weighted_edges_from([("A", "B", 1), ("B", "C", 1), ("A", "C", 5)])

r = gfnx.search(g, "A", "C", algorithm="dijkstra")
r.path            # ['A', 'B', 'C']
r.cost            # 2.0

# A* with a custom heuristic over your node labels:
gfnx.search(g, "A", "C", algorithm="astar", heuristic=lambda u, v: 0.0)

Use gfnx.to_edgelist(g) if you just want the (num_nodes, edges, index, labels, directed) mapping.

SciPy (scipy.sparse)

Search directly over a sparse adjacency matrix — comparable to scipy.sparse.csgraph.dijkstra / shortest_path, with the same directed convention (default True). Node ids are the matrix indices.

import scipy.sparse as sp
from graphfinder.integrations import scipy as gfsp

adj = sp.csr_matrix([[0, 1, 5], [0, 0, 1], [0, 0, 0]], dtype=float)
r = gfsp.search(adj, source=0, target=2, algorithm="dijkstra", directed=True)
r.path            # [0, 1, 2]
r.cost            # 2.0

pandas

Build a graph from an edge-list DataFrame, and turn results into tidy tables.

import pandas as pd
from graphfinder.integrations import pandas as gfpd

df = pd.DataFrame(
    [("A", "B", 1), ("B", "C", 1), ("A", "C", 5)],
    columns=["from", "to", "cost"],
)

r = gfpd.search(df, "A", "C", source="from", target="to", weight="cost",
                algorithm="dijkstra", record=True)
r.path            # ['A', 'B', 'C']

gfpd.trace_dataframe(r)       # step, node, g, frontier_size  (one row per expansion)
gfpd.compare_dataframe({      # one row per algorithm
    "bfs": gfpd.search(df, "A", "C", source="from", target="to"),
    "dijkstra": r,
})

compare_dataframe columns: found, cost, nodes_expanded, nodes_generated, max_frontier_size, path_len — the tabular companion to viz.compare.

OSMnx — routing on real road networks

Route over geographic graphs with an A* that uses a great-circle (haversine) heuristic. The core search works on any networkx graph whose nodes have x (lon) / y (lat) attributes — as OSMnx graphs do — and needs only networkx. The route / plot_route helpers snap lat/lon points to nodes and draw the route on the map, and require osmnx (pip install "graphfinder[osm]").

import osmnx as ox
from graphfinder.integrations import osm

G = ox.graph_from_place("Madrid, Spain", network_type="drive")

# Route between two (lat, lon) points — nearest nodes are found automatically.
r = osm.route(G, (40.4170, -3.7035), (40.4531, -3.6883))   # Sol → Bernabéu
print(r.cost, "metres,", len(r.path), "nodes,", r.nodes_expanded, "expanded")
osm.plot_route(G, r)

# Or search between known node ids directly (networkx-only):
osm.search(G, orig_id, dest_id, algorithm="astar")

Because the haversine heuristic is in metres and OSMnx edge length is in metres, A* is admissible and returns the shortest route while expanding far fewer nodes than Dijkstra.

Agents (LangChain) — a safe routing tool

Expose routing as an LLM tool. make_router builds a dependency-free, bound router(source, target, algorithm=None) -> dict that validates inputs, caps work with max_nodes, restricts the algorithm to a safe allow-list, and never raises — so it is safe inside an agent loop:

from graphfinder.integrations import agents

router = agents.make_router(edges)            # edges: (u, v[, weight]) with any labels
router("A", "E", algorithm="dijkstra")
# {'found': True, 'path': ['A','B','C','E'], 'cost': 3.0, 'nodes_expanded': ..., 'stop_reason': 'goal'}

Wrap it as a LangChain StructuredTool (needs langchain-core):

tool = agents.as_langchain_tool(edges, name="find_route")
tool.invoke({"source": "A", "target": "E"})

The graph is bound at tool-creation time; the agent only chooses source, target and an allowed algorithm.

Gymnasium — a GridWorld env with an A* oracle

A reinforcement-learning environment backed by a graphfinder grid. The agent goes from S to G; walls are #, digits 19 are terrain costs. Observations are the flattened cell index, actions are moves (4, or 8 with diagonal=True), and the reward is the negative cost of the entered cell.

from graphfinder.integrations import gym as gfgym

env = gfgym.GridWorldEnv("S....\n.###.\n....G")
obs, info = env.reset()

# A* oracle — useful for imitation learning, reward shaping or scoring an agent:
action = gfgym.optimal_action(env)   # the move A* would make from here
path = gfgym.optimal_path(env)       # the whole optimal path of cells

Graphviz — export graphs and paths

Render an edge-list graph (and a found path) to DOT/SVG. to_dot builds the DOT text with no dependency; source wraps it in a graphviz.Source you can render or display in a notebook (needs the graphviz package + dot binary).

from graphfinder.integrations import graphviz as gfgv
from graphfinder.integrations import pandas as gfpd

edges = [("A", "B", 1), ("B", "C", 1), ("A", "C", 5)]
r = gfpd.search(__import__("pandas").DataFrame(edges, columns=["source", "target", "weight"]),
                "A", "C")

print(gfgv.to_dot(edges, r))         # DOT string, path highlighted
gfgv.source(edges, r).render("route", format="svg")   # writes route.svg

Path nodes are gold, the start green, the goal red, and path edges are drawn thick.

More integrations

Have an idea (igraph, a different framework, …)? Open an issue.