@statelyai/graph 2.0.0 → 2.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/README.md +67 -19
  2. package/dist/{algorithms-CsGNehct.d.mts → algorithms-D1cgly0g.d.mts} +145 -6
  3. package/dist/{algorithms-DF1pSQGv.mjs → algorithms-DBpH74hR.mjs} +673 -891
  4. package/dist/algorithms.d.mts +2 -2
  5. package/dist/algorithms.mjs +2 -2
  6. package/dist/config-Dt5u1gSf.mjs +793 -0
  7. package/dist/{converter-DyCJJfTe.mjs → converter-DB6Rg6Vd.mjs} +2 -2
  8. package/dist/formats/adjacency-list/index.d.mts +1 -1
  9. package/dist/formats/adjacency-list/index.mjs +1 -1
  10. package/dist/formats/converter/index.d.mts +1 -1
  11. package/dist/formats/converter/index.mjs +1 -1
  12. package/dist/formats/cytoscape/index.d.mts +4 -4
  13. package/dist/formats/cytoscape/index.mjs +8 -4
  14. package/dist/formats/d2/index.d.mts +1 -1
  15. package/dist/formats/d2/index.mjs +1 -1
  16. package/dist/formats/d3/index.d.mts +4 -4
  17. package/dist/formats/d3/index.mjs +8 -4
  18. package/dist/formats/dot/index.d.mts +1 -1
  19. package/dist/formats/dot/index.mjs +1 -1
  20. package/dist/formats/edge-list/index.d.mts +1 -1
  21. package/dist/formats/edge-list/index.mjs +1 -1
  22. package/dist/formats/elk/index.d.mts +1 -1
  23. package/dist/formats/elk/index.mjs +43 -11
  24. package/dist/formats/gexf/index.d.mts +1 -1
  25. package/dist/formats/gexf/index.mjs +22 -2
  26. package/dist/formats/gml/index.d.mts +4 -4
  27. package/dist/formats/gml/index.mjs +8 -4
  28. package/dist/formats/graphml/index.d.mts +1 -1
  29. package/dist/formats/graphml/index.mjs +24 -2
  30. package/dist/formats/jgf/index.d.mts +4 -4
  31. package/dist/formats/jgf/index.mjs +8 -4
  32. package/dist/formats/mermaid/index.d.mts +1 -1
  33. package/dist/formats/mermaid/index.mjs +1 -1
  34. package/dist/formats/tgf/index.d.mts +4 -4
  35. package/dist/formats/tgf/index.mjs +4 -4
  36. package/dist/formats/xyflow/index.d.mts +12 -6
  37. package/dist/formats/xyflow/index.mjs +11 -6
  38. package/dist/{index-D51lJnt2.d.mts → index-BlbSWUvH.d.mts} +1 -1
  39. package/dist/{index-DWmo1mIp.d.mts → index-CNvqxPLJ.d.mts} +82 -14
  40. package/dist/index.d.mts +6 -6
  41. package/dist/index.mjs +152 -17
  42. package/dist/layout/cytoscape.d.mts +66 -0
  43. package/dist/layout/cytoscape.mjs +114 -0
  44. package/dist/layout/d3-force.d.mts +52 -0
  45. package/dist/layout/d3-force.mjs +127 -0
  46. package/dist/layout/d3-hierarchy.d.mts +39 -0
  47. package/dist/layout/d3-hierarchy.mjs +135 -0
  48. package/dist/layout/dagre.d.mts +32 -0
  49. package/dist/layout/dagre.mjs +99 -0
  50. package/dist/layout/elk.d.mts +47 -0
  51. package/dist/layout/elk.mjs +73 -0
  52. package/dist/layout/forceatlas2.d.mts +48 -0
  53. package/dist/layout/forceatlas2.mjs +100 -0
  54. package/dist/layout/graphviz.d.mts +50 -0
  55. package/dist/layout/graphviz.mjs +179 -0
  56. package/dist/layout/index.d.mts +185 -0
  57. package/dist/layout/index.mjs +181 -0
  58. package/dist/layout/webcola.d.mts +40 -0
  59. package/dist/layout/webcola.mjs +104 -0
  60. package/dist/{queries-BfXeTXRf.d.mts → queries-B6quF529.d.mts} +1 -1
  61. package/dist/{queries-KirMDR7e.mjs → queries-BMM0XAv_.mjs} +23 -17
  62. package/dist/queries.d.mts +1 -1
  63. package/dist/queries.mjs +1 -1
  64. package/dist/schemas.d.mts +19 -1
  65. package/dist/schemas.mjs +10 -1
  66. package/dist/{types-DNYdIU21.d.mts → types-BAEQTwK_.d.mts} +46 -3
  67. package/package.json +47 -5
  68. package/schemas/edge.schema.json +27 -0
  69. package/schemas/graph.schema.json +27 -0
  70. /package/dist/{adjacency-list-GeL1Cu-L.mjs → adjacency-list-DQ32Mmhx.mjs} +0 -0
  71. /package/dist/{edge-list-BcZ0h6zz.mjs → edge-list-CA9UTvn2.mjs} +0 -0
  72. /package/dist/{mode-D8OnHFBk.mjs → mode-gu_mhKKs.mjs} +0 -0
  73. /package/dist/{validate-TtH-x3JV.mjs → validate-BsfSOv0S.mjs} +0 -0
package/README.md CHANGED
@@ -14,14 +14,19 @@ Optional peers are only needed for specific adapters:
14
14
 
15
15
  <!-- optional peer dependencies derived from package.json#peerDependencies -->
16
16
 
17
- | Package | Needed for |
18
- | ----------------- | --------------------------------------------------- |
19
- | `fast-xml-parser` | `@statelyai/graph/gexf`, `@statelyai/graph/graphml` |
20
- | `dotparser` | `@statelyai/graph/dot` parsing |
21
- | `cytoscape` | Cytoscape integration tests and consumer typing |
22
- | `d3-force` | D3 force integration tests and consumer typing |
23
- | `elkjs` | `@statelyai/graph/elk` |
24
- | `zod` | `@statelyai/graph/schemas` |
17
+ | Package | Needed for |
18
+ | ------------------------------------------- | --------------------------------------------------- |
19
+ | `fast-xml-parser` | `@statelyai/graph/gexf`, `@statelyai/graph/graphml` |
20
+ | `dotparser` | `@statelyai/graph/dot` parsing |
21
+ | `zod` | `@statelyai/graph/schemas` |
22
+ | `elkjs` | `@statelyai/graph/elk`, `@statelyai/graph/layout/elk` |
23
+ | `@dagrejs/dagre` | `@statelyai/graph/layout/dagre` |
24
+ | `@hpcc-js/wasm-graphviz` | `@statelyai/graph/layout/graphviz` |
25
+ | `d3-force` | `@statelyai/graph/layout/d3-force` |
26
+ | `graphology`, `graphology-layout-forceatlas2` | `@statelyai/graph/layout/forceatlas2` |
27
+ | `d3-hierarchy` | `@statelyai/graph/layout/d3-hierarchy` |
28
+ | `webcola` | `@statelyai/graph/layout/webcola` |
29
+ | `cytoscape` | `@statelyai/graph/layout/cytoscape`, Cytoscape format typing |
25
30
 
26
31
  ## Highlights
27
32
 
@@ -29,7 +34,8 @@ Optional peers are only needed for specific adapters:
29
34
  - Standalone functions with a consistent `get*`/`gen*`/`is*`/`add*` naming model
30
35
  - Directed, undirected, hierarchical, and visual graph support
31
36
  - Ports for node-editor and dataflow-style graphs
32
- - Algorithms for traversal, paths, centrality, communities, connectivity, isomorphism, ordering, MST, and walks
37
+ - Algorithms for traversal, paths, centrality, communities, connectivity, flow/cuts, matching, cores, isomorphism, ordering, MST, and walks
38
+ - Pluggable layout over eight external engines (ELK, Graphviz, dagre, d3-force, ForceAtlas2, tidy tree, WebCola, cytoscape) — pure functions, optional peers
33
39
  - Diff/patch utilities for graph state changes
34
40
  - Multi-format conversion via package subpaths, with fidelity claims tested against fixtures
35
41
  - Small, fast test suite with broad format coverage
@@ -96,10 +102,10 @@ updateNode(graph, 'a', { color: null }); // unset
96
102
 
97
103
  ## Hierarchy
98
104
 
99
- Nodes support parent-child relationships for compound/nested graphs. Query children, ancestors, descendants, depth, and least common ancestor. Use `flatten()` to decompose into a flat leaf-node graph.
105
+ Nodes support parent-child relationships for compound/nested graphs. Query children, ancestors, descendants, depth, and least common ancestor. Use `getFlattenedGraph()` to decompose into a flat leaf-node graph.
100
106
 
101
107
  ```ts
102
- import { createGraph, getChildren, getLCA, flatten } from '@statelyai/graph';
108
+ import { createGraph, getChildren, getLCA, getFlattenedGraph } from '@statelyai/graph';
103
109
 
104
110
  const graph = createGraph({
105
111
  nodes: [
@@ -117,7 +123,7 @@ const graph = createGraph({
117
123
  });
118
124
 
119
125
  const children = getChildren(graph, 'b'); // [b1, b2]
120
- const flat = flatten(graph); // only leaf nodes, edges resolved
126
+ const flat = getFlattenedGraph(graph); // only leaf nodes, edges resolved
121
127
  ```
122
128
 
123
129
  ## Ports
@@ -188,14 +194,14 @@ const parsed = GraphSchema.parse(unknownValue);
188
194
 
189
195
  <!-- algorithm functions exported from src/algorithms.ts -->
190
196
 
191
- Includes traversal (BFS, DFS, preorder/postorder), pathfinding (shortest path, simple paths, all-pairs shortest paths, A*), centrality/link analysis (degree, closeness, betweenness, PageRank, HITS, eigenvector), community detection (Louvain, label propagation, Girvan-Newman, greedy modularity, modularity scoring), flow (max-flow/min-cut), cycle detection, connected/strongly-connected components, bridges, articulation points, biconnected components, dominator trees, transitive reduction, isomorphism, topological sort, minimum spanning tree, and more. Many algorithms have lazy generator variants (`gen*`) for early exit.
197
+ Includes traversal (BFS, DFS, preorder/postorder), pathfinding (shortest path, simple paths, all-pairs shortest paths, A*, bidirectional Dijkstra), centrality/link analysis (degree, closeness, betweenness, PageRank, HITS, eigenvector, Katz), community detection (Louvain, label propagation, Girvan-Newman, greedy modularity, modularity scoring), flow & cuts (`getMaxFlow`, `getMinCut`), bipartite analysis (`isBipartite`, Hopcroft–Karp `getMaximumBipartiteMatching`), k-cores (`getCoreNumbers`, `getKCore`), cycle detection, connected/strongly-connected components, bridges, articulation points, biconnected components, dominator trees, transitive reduction, isomorphism, topological sort, minimum spanning tree, and seeded graph generators (`createCompleteGraph`, `createGridGraph`, `createRandomGraph`). Many algorithms have lazy generator variants (`gen*`) for early exit. See [docs/algorithms.md](./docs/algorithms.md) for the full reference.
192
198
 
193
199
  Hot algorithm loops (centrality, components) run on an internal compressed-sparse-row snapshot — cached and invalidated transparently like the rest of the index — so they stay fast on large graphs without changing the plain-JSON model. Algorithm results are differential-tested against graphology on seeded random graphs.
194
200
 
195
201
  ```ts
196
202
  import {
197
- bfs,
198
- dfs,
203
+ genBFS,
204
+ genDFS,
199
205
  hasPath,
200
206
  isAcyclic,
201
207
  getShortestPath,
@@ -214,10 +220,10 @@ import {
214
220
  isIsomorphic,
215
221
  } from '@statelyai/graph';
216
222
 
217
- for (const node of bfs(graph, 'a')) {
223
+ for (const node of genBFS(graph, 'a')) {
218
224
  /* breadth-first */
219
225
  }
220
- for (const node of dfs(graph, 'a')) {
226
+ for (const node of genDFS(graph, 'a')) {
221
227
  /* depth-first */
222
228
  }
223
229
 
@@ -238,13 +244,44 @@ getTransitiveReduction(graph); // minimal equivalent DAG
238
244
  isIsomorphic(graph, otherGraph); // structural equivalence
239
245
  ```
240
246
 
247
+ ## Layout
248
+
249
+ <!-- layout adapters under src/layout/*.ts and helpers exported from src/layout/index.ts -->
250
+
251
+ Plug-and-play layout over external engines — pure functions in, positioned `VisualGraph` out. No layout algorithms of our own; each adapter is a subpath with an optional peer dependency. The hierarchical engines (ELK, dagre, Graphviz) also produce routed edge `points` and computed edge-label rects; the physics/tree/cytoscape engines position nodes only.
252
+
253
+ ```ts
254
+ import { getElkLayout } from '@statelyai/graph/layout/elk'; // elkjs
255
+ import { getDagreLayout } from '@statelyai/graph/layout/dagre'; // @dagrejs/dagre
256
+ import { getGraphvizLayout } from '@statelyai/graph/layout/graphviz'; // @hpcc-js/wasm-graphviz (8 engines)
257
+ import { genForceLayout } from '@statelyai/graph/layout/d3-force'; // d3-force
258
+ import { getForceAtlas2Layout } from '@statelyai/graph/layout/forceatlas2'; // graphology FA2
259
+ import { getTidyTreeLayout } from '@statelyai/graph/layout/d3-hierarchy'; // d3-hierarchy
260
+ import { getColaLayout } from '@statelyai/graph/layout/webcola'; // webcola (constraints)
261
+ import { getCytoscapeLayout } from '@statelyai/graph/layout/cytoscape'; // cytoscape ecosystem
262
+ import { applyLayoutFrame, getLayoutBounds, centerGraph } from '@statelyai/graph/layout';
263
+
264
+ const laidOut = await getElkLayout(graph, {
265
+ measure: (node) => measureText(node.label), // text measurement stays yours
266
+ constraints: { layer: (node) => node.data?.tier }, // portable layer constraint
267
+ });
268
+
269
+ // Physics layouts are generators — one tick per frame, cancel by stopping
270
+ for (const frame of genForceLayout(graph, { seed: 42 })) {
271
+ applyLayoutFrame(graph, frame);
272
+ render(graph);
273
+ }
274
+ ```
275
+
276
+ Edge `x`/`y`/`width`/`height` are canonically the edge-label rect; routes live in `edge.points` (`routing` says how to interpret them). Layouts are plain JSON — tween between engines with `genLayoutTransition`, or diff them with `getPatches`. See [docs/layout.md](./docs/layout.md) and [docs/layout-transitions.md](./docs/layout-transitions.md).
277
+
241
278
  ## Diff & Walks
242
279
 
243
280
  Beyond classic graph algorithms, the library also includes utilities for evolving and exploring graph state:
244
281
 
245
- - `getDiff()`, `getPatches()`, `applyPatches()` for graph change tracking
282
+ - `getDiff()`, `getPatches()`, `updateGraphWithPatches()` for graph change tracking
246
283
  - `genRandomWalk()`, `genWeightedRandomWalk()`, and coverage helpers for model-based testing and simulation
247
- - `getSubgraph()` and `reverseGraph()` for structural transforms
284
+ - `getSubgraph()` and `getReversedGraph()` for structural transforms
248
285
 
249
286
  ## Visual Graphs
250
287
 
@@ -347,6 +384,17 @@ Format-specific docs live alongside the source:
347
384
  - [xyflow](./src/formats/xyflow/README.md)
348
385
  - [Converter helpers](./src/formats/converter/README.md)
349
386
 
387
+ ## Guides
388
+
389
+ <!-- guide documents under docs/*.md -->
390
+
391
+ - [Layout guide](./docs/layout.md) — the adapter contract, all eight engines, constraints, sizing, web workers
392
+ - [Layout transitions](./docs/layout-transitions.md) — tween between engines; layouts are just data
393
+ - [Algorithms reference](./docs/algorithms.md) — every algorithm with complexity and semantics notes
394
+ - [Benchmarks](./docs/benchmarks.md) — measured against graphology, ngraph, graphlib, and cytoscape
395
+ - [Migrating from graphlib](./docs/migrating-from-graphlib.md)
396
+ - [React Flow + ELK pipeline](./docs/react-flow-elk-pipeline.md) — measured nodes, worker layout, live re-layout
397
+
350
398
  ## Examples
351
399
 
352
400
  <!-- runnable example files under examples/ -->
@@ -1,7 +1,15 @@
1
- import { A as SinglePathOptions, C as MSTOptions, D as PathOptions, M as TraversalOptions, b as GraphPath, d as Graph, m as GraphEdge, n as AllPairsShortestPathsOptions, t as AStarOptions, v as GraphNode } from "./types-DNYdIU21.mjs";
1
+ import { M as SinglePathOptions, O as PathOptions, P as TraversalOptions, f as Graph, h as GraphEdge, n as AllPairsShortestPathsOptions, t as AStarOptions, w as MSTOptions, x as GraphPath, y as GraphNode } from "./types-BAEQTwK_.mjs";
2
2
 
3
3
  //#region src/algorithms/traversal.d.ts
4
+ declare function genBFS<N>(graph: Graph<N>, startId: string): Generator<GraphNode<N>>;
5
+ /**
6
+ * @deprecated Use {@link genBFS}.
7
+ */
4
8
  declare function bfs<N>(graph: Graph<N>, startId: string): Generator<GraphNode<N>>;
9
+ declare function genDFS<N>(graph: Graph<N>, startId: string): Generator<GraphNode<N>>;
10
+ /**
11
+ * @deprecated Use {@link genDFS}.
12
+ */
5
13
  declare function dfs<N>(graph: Graph<N>, startId: string): Generator<GraphNode<N>>;
6
14
  declare function isAcyclic(graph: Graph): boolean;
7
15
  declare function getConnectedComponents<N>(graph: Graph<N>): GraphNode<N>[][];
@@ -35,6 +43,10 @@ declare function getCycles<N, E>(graph: Graph<N, E>): GraphPath<N, E>[];
35
43
  declare function genCycles<N, E>(graph: Graph<N, E>): Generator<GraphPath<N, E>>;
36
44
  declare function getAllPairsShortestPaths<N, E>(graph: Graph<N, E>, opts?: AllPairsShortestPathsOptions<E>): GraphPath<N, E>[];
37
45
  declare function getAStarPath<N, E>(graph: Graph<N, E>, opts: AStarOptions<E>): GraphPath<N, E> | undefined;
46
+ declare function getJoinedPath<N, E>(headPath: GraphPath<N, E>, tailPath: GraphPath<N, E>): GraphPath<N, E>;
47
+ /**
48
+ * @deprecated Use {@link getJoinedPath}.
49
+ */
38
50
  declare function joinPaths<N, E>(headPath: GraphPath<N, E>, tailPath: GraphPath<N, E>): GraphPath<N, E>;
39
51
  //#endregion
40
52
  //#region src/algorithms/ordering.d.ts
@@ -54,6 +66,16 @@ interface IterativeCentralityOptions {
54
66
  maxIterations?: number;
55
67
  tolerance?: number;
56
68
  }
69
+ interface EigenvectorCentralityOptions<E = any> extends IterativeCentralityOptions {
70
+ /** Edge weight accessor. Defaults to unweighted (every edge counts 1). */
71
+ getWeight?: (edge: GraphEdge<E>) => number;
72
+ }
73
+ interface KatzCentralityOptions<E = any> extends IterativeCentralityOptions {
74
+ /** Constant added to every node each iteration. Defaults to `1`. */
75
+ beta?: number;
76
+ /** Edge weight accessor. Defaults to unweighted (every edge counts 1). */
77
+ getWeight?: (edge: GraphEdge<E>) => number;
78
+ }
57
79
  interface HITSResult {
58
80
  hubs: Record<string, number>;
59
81
  authorities: Record<string, number>;
@@ -111,10 +133,81 @@ declare function getHITS(graph: Graph, options?: IterativeCentralityOptions): HI
111
133
  /**
112
134
  * Returns eigenvector centrality scores for all nodes.
113
135
  *
114
- * Uses power iteration over incoming neighbors for directed graphs and
115
- * undirected adjacency for undirected graphs.
136
+ * Power iteration with the `A + I` shift (same scheme as graphology and
137
+ * networkx, so bipartite structures converge instead of oscillating).
138
+ * Scores flow along edge direction: a node's score is fed by its incoming
139
+ * neighbors; undirected edges feed both endpoints. The result vector is
140
+ * Euclidean (L2) normalized.
141
+ *
142
+ * Throws when the iteration has not converged (L1 error < `n × tolerance`)
143
+ * within `maxIterations`.
144
+ */
145
+ declare function getEigenvectorCentrality<N, E>(graph: Graph<N, E>, options?: EigenvectorCentralityOptions<E>): Record<string, number>;
146
+ /**
147
+ * Returns Katz centrality scores for all nodes.
148
+ *
149
+ * Iterates `x' = alpha · Aᵀx + beta` to its fixed point (networkx-style),
150
+ * then Euclidean (L2) normalizes the result. Scores flow along edge
151
+ * direction: a node's score is fed by its incoming neighbors; undirected
152
+ * edges feed both endpoints.
153
+ *
154
+ * Converges only when `alpha` is below the reciprocal of the largest
155
+ * eigenvalue of the adjacency matrix; throws when the iteration has not
156
+ * converged (L1 error < `n × tolerance`) within `maxIterations`.
157
+ */
158
+ declare function getKatzCentrality<N, E>(graph: Graph<N, E>, options?: KatzCentralityOptions<E>): Record<string, number>;
159
+ //#endregion
160
+ //#region src/algorithms/cores.d.ts
161
+ /**
162
+ * Returns the core number of every node (largest `k` such that the node
163
+ * belongs to the k-core).
164
+ *
165
+ * Uses Batagelj–Zaveršnik bucket peeling — O(m). Edges are treated as
166
+ * undirected (the standard k-core definition); self-loops are ignored.
167
+ *
168
+ * @example
169
+ * ```ts
170
+ * const cores = getCoreNumbers(graph);
171
+ * console.log(cores.a); // 3
172
+ * ```
173
+ */
174
+ declare function getCoreNumbers(graph: Graph): Record<string, number>;
175
+ /**
176
+ * Returns the ids of all nodes in the k-core: the maximal subgraph in which
177
+ * every node has at least `k` neighbors (edges treated as undirected).
178
+ *
179
+ * Node order follows `graph.nodes`. `k <= 0` returns every node id.
116
180
  */
117
- declare function getEigenvectorCentrality(graph: Graph, options?: IterativeCentralityOptions): Record<string, number>;
181
+ declare function getKCore(graph: Graph, k: number): string[];
182
+ //#endregion
183
+ //#region src/algorithms/bipartite.d.ts
184
+ interface BipartiteMatch {
185
+ /** Source node id of the matched edge (as stored on the edge). */
186
+ sourceId: string;
187
+ /** Target node id of the matched edge (as stored on the edge). */
188
+ targetId: string;
189
+ /** Id of the edge realizing the match. */
190
+ edgeId: string;
191
+ }
192
+ /**
193
+ * Returns whether the graph is bipartite (2-colorable).
194
+ *
195
+ * Edges are treated as undirected; self-loops make a graph non-bipartite.
196
+ * Runs a BFS 2-coloring per connected component — O(n + m).
197
+ */
198
+ declare function isBipartite(graph: Graph): boolean;
199
+ /**
200
+ * Returns a maximum-cardinality matching of a bipartite graph using
201
+ * Hopcroft–Karp — O(m·√n).
202
+ *
203
+ * The bipartition is derived by 2-coloring (edges treated as undirected).
204
+ * Each match reports the realizing edge with its stored `sourceId`/
205
+ * `targetId` orientation; for parallel edges between a matched pair, the
206
+ * first edge used by the algorithm is reported.
207
+ *
208
+ * Throws if the graph is not bipartite, naming the offending edge.
209
+ */
210
+ declare function getMaximumBipartiteMatching(graph: Graph): BipartiteMatch[];
118
211
  //#endregion
119
212
  //#region src/algorithms/community.d.ts
120
213
  interface GirvanNewmanOptions {
@@ -123,13 +216,21 @@ interface GirvanNewmanOptions {
123
216
  }
124
217
  interface LabelPropagationOptions {
125
218
  maxIterations?: number;
219
+ /**
220
+ * When provided, runs *asynchronous* label propagation with a shuffled
221
+ * node order per round and random tie-breaking, seeded with mulberry32 —
222
+ * deterministic per seed. Without a seed, ties break lexicographically.
223
+ */
224
+ seed?: number;
126
225
  }
127
226
  type Community<N = any> = GraphNode<N>[];
128
227
  /**
129
228
  * Returns label-propagation communities for the graph.
130
229
  *
131
230
  * The implementation is deterministic: ties are broken by lexicographic label
132
- * order so test results remain stable.
231
+ * order so test results remain stable. Pass `options.seed` for the classic
232
+ * asynchronous variant (shuffled node order per round, random tie-breaking)
233
+ * — still deterministic per seed.
133
234
  */
134
235
  declare function getLabelPropagationCommunities<N>(graph: Graph<N>, options?: LabelPropagationOptions): Community<N>[];
135
236
  /**
@@ -238,6 +339,25 @@ interface MaxFlowResult<E = any> {
238
339
  /** Edges in the minimum cut (max-flow-min-cut theorem). */
239
340
  cutEdges: GraphEdge<E>[];
240
341
  }
342
+ interface MinCutOptions<E = any> {
343
+ /** Source node id. */
344
+ source: string;
345
+ /** Sink node id. */
346
+ sink: string;
347
+ /** Edge capacity accessor. Defaults to `edge.weight ?? 1`. */
348
+ getCapacity?: (edge: GraphEdge<E>) => number;
349
+ }
350
+ interface MinCutResult {
351
+ /** Total capacity of the cut (equals the max-flow value). */
352
+ value: number;
353
+ /** Ids of the edges crossing the cut. */
354
+ cutEdges: string[];
355
+ /** Node ids on each side of the cut, in `graph.nodes` order. */
356
+ partition: {
357
+ source: string[];
358
+ sink: string[];
359
+ };
360
+ }
241
361
  /**
242
362
  * Returns the maximum flow from `from` to `to` using the Edmonds-Karp
243
363
  * algorithm (BFS augmenting paths).
@@ -257,6 +377,25 @@ interface MaxFlowResult<E = any> {
257
377
  * ```
258
378
  */
259
379
  declare function getMaxFlow<N, E>(graph: Graph<N, E>, options: MaxFlowOptions<E>): MaxFlowResult<E>;
380
+ /**
381
+ * Returns a minimum s-t cut between `source` and `sink` via the max-flow
382
+ * min-cut theorem: runs the same Edmonds-Karp solver as {@link getMaxFlow},
383
+ * then splits the nodes by residual reachability from the source.
384
+ *
385
+ * `partition.source` holds every node reachable from `source` in the final
386
+ * residual graph; `partition.sink` holds the rest (both in `graph.nodes`
387
+ * order). `cutEdges` are the ids of the edges crossing the cut, and their
388
+ * total capacity equals `value` (the max-flow value).
389
+ *
390
+ * @example
391
+ * ```ts
392
+ * const { value, cutEdges, partition } = getMinCut(graph, {
393
+ * source: 's',
394
+ * sink: 't',
395
+ * });
396
+ * ```
397
+ */
398
+ declare function getMinCut<N, E>(graph: Graph<N, E>, options: MinCutOptions<E>): MinCutResult;
260
399
  //#endregion
261
400
  //#region src/algorithms/dominators.d.ts
262
401
  interface DominatorTreeOptions {
@@ -310,4 +449,4 @@ declare function getDominatorTree(graph: Graph, options?: DominatorTreeOptions):
310
449
  */
311
450
  declare function getTransitiveReduction<N, E, G, P>(graph: Graph<N, E, G, P>): Graph<N, E, G, P>;
312
451
  //#endregion
313
- export { getTopologicalSort as $, getPageRank as A, genSimplePaths as B, getBetweennessCentrality as C, getHITS as D, getEigenvectorCentrality as E, getPostorders as F, getShortestPaths as G, getAllPairsShortestPaths as H, getPreorder as I, getStronglyConnectedComponents as J, getSimplePath as K, getPreorders as L, genPostorders as M, genPreorders as N, getInDegreeCentrality as O, getPostorder as P, getConnectedComponents as Q, genCycles as R, IterativeCentralityOptions as S, getDegreeCentrality as T, getCycles as U, getAStarPath as V, getShortestPath as W, bfs as X, joinPaths as Y, dfs as Z, getGirvanNewmanCommunities as _, MaxFlowResult as a, getModularity as b, getLouvainCommunities as c, getArticulationPoints as d, hasPath as et, getBiconnectedComponents as f, genGirvanNewmanCommunities as g, LabelPropagationOptions as h, MaxFlowOptions as i, getMinimumSpanningTree as j, getOutDegreeCentrality as k, IsomorphismOptions as l, GirvanNewmanOptions as m, DominatorTreeOptions as n, isConnected as nt, getMaxFlow as o, getBridges as p, getSimplePaths as q, getDominatorTree as r, isTree as rt, LouvainOptions as s, getTransitiveReduction as t, isAcyclic as tt, isIsomorphic as u, getGreedyModularityCommunities as v, getClosenessCentrality as w, HITSResult as x, getLabelPropagationCommunities as y, genShortestPaths as z };
452
+ export { getAllPairsShortestPaths as $, HITSResult as A, getOutDegreeCentrality as B, getModularity as C, getCoreNumbers as D, isBipartite as E, getDegreeCentrality as F, getPostorder as G, getMinimumSpanningTree as H, getEigenvectorCentrality as I, getPreorders as J, getPostorders as K, getHITS as L, KatzCentralityOptions as M, getBetweennessCentrality as N, getKCore as O, getClosenessCentrality as P, getAStarPath as Q, getInDegreeCentrality as R, getLabelPropagationCommunities as S, getMaximumBipartiteMatching as T, genPostorders as U, getPageRank as V, genPreorders as W, genShortestPaths as X, genCycles as Y, genSimplePaths as Z, GirvanNewmanOptions as _, isTree as _t, MaxFlowResult as a, getSimplePaths as at, getGirvanNewmanCommunities as b, getMaxFlow as c, bfs as ct, getLouvainCommunities as d, genDFS as dt, getCycles as et, IsomorphismOptions as f, getConnectedComponents as ft, getBridges as g, isConnected as gt, getBiconnectedComponents as h, isAcyclic as ht, MaxFlowOptions as i, getSimplePath as it, IterativeCentralityOptions as j, EigenvectorCentralityOptions as k, getMinCut as l, dfs as lt, getArticulationPoints as m, hasPath as mt, DominatorTreeOptions as n, getShortestPath as nt, MinCutOptions as o, getStronglyConnectedComponents as ot, isIsomorphic as p, getTopologicalSort as pt, getPreorder as q, getDominatorTree as r, getShortestPaths as rt, MinCutResult as s, joinPaths as st, getTransitiveReduction as t, getJoinedPath as tt, LouvainOptions as u, genBFS as ut, LabelPropagationOptions as v, BipartiteMatch as w, getGreedyModularityCommunities as x, genGirvanNewmanCommunities as y, getKatzCentrality as z };