Liking cljdoc? Tell your friends :D

cljgrapht

Clojars Project cljdoc test

A Clojure graph library that uses JGraphT. You build graphs over plain Clojure values, run JGraphT's algorithms, and get plain Clojure data back.

Stack

Clojure deps.edn tools.build JGraphT

Why

Python's networkx is slow because it is pure Python. Graph algorithms are irregular and they chase pointers, so they do not vectorize into a C core as numpy workloads do. On the JVM the same algorithms run on JIT-compiled code with real threads.

loom and ubergraph are pure-Clojure graph libraries. Use one of them if it covers your needs. cljgrapht uses a different approach. It does not write the algorithms in Clojure. It wraps JGraphT and puts a Clojure API in front of the JGraphT algorithm catalog (shortest paths, centrality, flow, matching, coloring, isomorphism, and more). Use cljgrapht when you want an algorithm that the pure-Clojure libraries do not have, or when you want JGraphT's performance on large graphs. A vertex can be any Clojure value. Results come back as vectors, sets, and maps.

This is a performance wrapper, not a persistent data structure. Graphs are JGraphT's native mutable objects. Constructors and mutators return the graph so that you can thread calls, but they mutate the graph in place.

Requires JDK 11+ (JGraphT 1.5.x).

Installation

tools.deps (deps.edn):

net.clojars.savya/cljgrapht {:mvn/version "1.1.2"}

Leiningen (project.clj):

[net.clojars.savya/cljgrapht "1.1.2"]

Run tests with clojure -M:test. Build a jar with clojure -T:build jar and deploy to Clojars with clojure -T:build deploy.

Usage

(require '[cljgrapht.core :as g]
         '[cljgrapht.algo :as a])

;; Build a weighted directed graph from edge data.
(def road
  (g/weighted-digraph [[:a :b 1.0] [:a :c 4.0] [:b :c 1.0] [:c :d 1.0]]))

;; Cheapest route, as Clojure data.
(a/shortest-path road :a :d)
;; => {:path [:a :b :c :d] :weight 3.0}

;; Undirected social graph; who is most central?
(def social (g/graph [[:alice :bob] [:bob :carol] [:bob :dave] [:carol :dave]]))

(a/betweenness-centrality social)
;; => {:alice 0.0 :bob 2.0 :carol 0.0 :dave 0.0}

;; Dependency graph: order tasks, or detect a cycle.
(def deps (g/digraph [[:compile :test] [:compile :package] [:test :deploy]
                      [:package :deploy]]))

(a/topological-sort deps) ;; => [:compile :test :package :deploy]
(a/cycle? deps)           ;; => false

What's in cljgrapht.algo

  • Shortest paths: shortest-path, shortest-path-length, astar, bellman-ford, bellman-ford-distances, all-pairs-shortest-path-length, johnson-all-pairs, k-shortest-paths, all-simple-paths
  • Connectivity: connected-components, strongly-connected-components, connected?, strongly-connected?
  • Ordering & cycles: topological-sort, dag?, cycle?, vertices-on-cycles, simple-cycles
  • Spanning: minimum-spanning-tree
  • Matching: maximum-matching (Edmonds), maximum-weight-matching (Kolmogorov blossom V), bipartite-matching (Hopcroft-Karp), bipartite?, bipartite-sets
  • Flow: max-flow, min-cut (push-relabel; edge weights are capacities)
  • Coloring: coloring (DSatur default; :greedy, :largest-degree-first, :smallest-degree-last via :algorithm), greedy-coloring
  • Link prediction: eight standard predictors via link-prediction-score and predict-links
  • Lowest common ancestor: lca and lca-set with naive and rooted variants
  • Steiner trees: approximate weighted steiner-tree
  • Line graphs: line-graph, including optional edge-weight conversion
  • Dense subgraphs: maximum-density-subgraph with caller-provided sentinels
  • Centrality: betweenness-centrality, closeness-centrality, pagerank
  • Graph shape and scoring: maximal-cliques, clustering-coefficient, global-clustering-coefficient, coreness, density, isolated-vertices, isomorphic?

What's in cljgrapht.gen

  • Graph generators: complete-graph, ring-graph, star-graph, grid-graph
  • Seedable random generators: gnp-random-graph, barabasi-albert-graph, watts-strogatz-graph

What's in cljgrapht.io

  • DOT: dot, write-dot!, read-dot
  • GraphML: graphml, write-graphml!

Loom interop

cljgrapht.loom extends loom's Graph, Digraph, WeightedGraph, and EditableGraph protocols to raw org.jgrapht.Graph, so loom's generic algorithms (loom.alg) run directly on cljgrapht graphs:

(require '[cljgrapht.core :as g]
         '[cljgrapht.loom]  ;; load the protocol extensions
         '[loom.alg :as alg])

(def gr (g/weighted-digraph [[:a :b 1.0] [:a :c 10.0] [:b :c 1.0]]))
(alg/dijkstra-path gr :a :c) ;; => (:a :b :c)

Loom is not a dependency of cljgrapht. Add a loom artifact (net.clojars.savya/loom or aysylu/loom) to your own deps before you require cljgrapht.loom. Loom's EditableGraph operations mutate the underlying JGraphT graph in place and return the same instance. Loom's persistent graph records behave differently.

Performance

These benchmarks use random weighted digraphs and criterium quick-bench. They use Clojure 1.12.5 and JDK 17. They exclude graph construction from the algorithm rows. Source: bench/bench.clj.

2,000 vertices / ~10k edges

Taskloom 1.0.2ubergraph 0.9.0cljgrapht
Build from edge list201 ms27 ms4.7 ms
Weighted shortest path (Dijkstra)7.3 ms5.2 ms0.27 ms
Connected components6.0 ms22 ms1.9 ms

10,000 vertices / ~50k edges

Taskloom 1.0.2ubergraph 0.9.0cljgrapht
Build from edge list963 ms182 ms27 ms
Weighted shortest path (Dijkstra)20 ms8.1 ms1.1 ms
Connected components28 ms95 ms13 ms

This is the tradeoff of a native Java engine. loom and ubergraph use persistent, immutable graphs. cljgrapht uses mutable graphs instead. Use cljgrapht when graph size or algorithm depth is the constraint.

License

Copyright © 2026 Savyasachi

Distributed under the Eclipse Public License 2.0, the same license JGraphT is available under.

Can you improve this documentation?Edit on GitHub

cljdoc builds & hosts documentation for Clojure/Script libraries

Keyboard shortcuts
Ctrl+kJump to recent docs
Move to previous article
Move to next article
Ctrl+/Jump to the search field
× close