effect 3.17.13 → 3.18.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.
- package/Graph/package.json +6 -0
- package/dist/cjs/Context.js +11 -3
- package/dist/cjs/Context.js.map +1 -1
- package/dist/cjs/Effect.js.map +1 -1
- package/dist/cjs/ExecutionPlan.js +4 -4
- package/dist/cjs/Graph.js +2964 -0
- package/dist/cjs/Graph.js.map +1 -0
- package/dist/cjs/Predicate.js +2 -3
- package/dist/cjs/Predicate.js.map +1 -1
- package/dist/cjs/Tracer.js.map +1 -1
- package/dist/cjs/index.js +4 -2
- package/dist/cjs/index.js.map +1 -1
- package/dist/cjs/internal/core-effect.js +1 -1
- package/dist/cjs/internal/core-effect.js.map +1 -1
- package/dist/cjs/internal/effect/circular.js +12 -2
- package/dist/cjs/internal/effect/circular.js.map +1 -1
- package/dist/cjs/internal/metric/hook.js +6 -1
- package/dist/cjs/internal/metric/hook.js.map +1 -1
- package/dist/cjs/internal/version.js +1 -1
- package/dist/cjs/internal/version.js.map +1 -1
- package/dist/dts/Context.d.ts +27 -3
- package/dist/dts/Context.d.ts.map +1 -1
- package/dist/dts/Effect.d.ts +4 -0
- package/dist/dts/Effect.d.ts.map +1 -1
- package/dist/dts/ExecutionPlan.d.ts +8 -8
- package/dist/dts/Graph.d.ts +1652 -0
- package/dist/dts/Graph.d.ts.map +1 -0
- package/dist/dts/Predicate.d.ts +2 -3
- package/dist/dts/Predicate.d.ts.map +1 -1
- package/dist/dts/Tracer.d.ts +1 -1
- package/dist/dts/Tracer.d.ts.map +1 -1
- package/dist/dts/index.d.ts +5 -0
- package/dist/dts/index.d.ts.map +1 -1
- package/dist/dts/internal/core-effect.d.ts.map +1 -1
- package/dist/esm/Context.js +10 -2
- package/dist/esm/Context.js.map +1 -1
- package/dist/esm/Effect.js.map +1 -1
- package/dist/esm/ExecutionPlan.js +4 -4
- package/dist/esm/Graph.js +2905 -0
- package/dist/esm/Graph.js.map +1 -0
- package/dist/esm/Predicate.js +2 -3
- package/dist/esm/Predicate.js.map +1 -1
- package/dist/esm/Tracer.js.map +1 -1
- package/dist/esm/index.js +5 -0
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/internal/core-effect.js +1 -1
- package/dist/esm/internal/core-effect.js.map +1 -1
- package/dist/esm/internal/effect/circular.js +12 -2
- package/dist/esm/internal/effect/circular.js.map +1 -1
- package/dist/esm/internal/metric/hook.js +6 -1
- package/dist/esm/internal/metric/hook.js.map +1 -1
- package/dist/esm/internal/version.js +1 -1
- package/dist/esm/internal/version.js.map +1 -1
- package/package.json +9 -1
- package/src/Context.ts +28 -3
- package/src/Effect.ts +5 -0
- package/src/ExecutionPlan.ts +8 -8
- package/src/Graph.ts +3564 -0
- package/src/Predicate.ts +2 -3
- package/src/Tracer.ts +2 -1
- package/src/index.ts +6 -0
- package/src/internal/core-effect.ts +2 -1
- package/src/internal/effect/circular.ts +31 -17
- package/src/internal/metric/hook.ts +6 -1
- package/src/internal/version.ts +1 -1
|
@@ -0,0 +1,1652 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @experimental
|
|
3
|
+
* @since 3.18.0
|
|
4
|
+
*/
|
|
5
|
+
import * as Data from "./Data.js";
|
|
6
|
+
import * as Equal from "./Equal.js";
|
|
7
|
+
import type { Inspectable } from "./Inspectable.js";
|
|
8
|
+
import * as Option from "./Option.js";
|
|
9
|
+
import type { Pipeable } from "./Pipeable.js";
|
|
10
|
+
/**
|
|
11
|
+
* Unique identifier for Graph instances.
|
|
12
|
+
*
|
|
13
|
+
* @since 3.18.0
|
|
14
|
+
* @category symbol
|
|
15
|
+
*/
|
|
16
|
+
export declare const TypeId: "~effect/Graph";
|
|
17
|
+
/**
|
|
18
|
+
* Type identifier for Graph instances.
|
|
19
|
+
*
|
|
20
|
+
* @since 3.18.0
|
|
21
|
+
* @category symbol
|
|
22
|
+
*/
|
|
23
|
+
export type TypeId = typeof TypeId;
|
|
24
|
+
/**
|
|
25
|
+
* Node index for node identification using plain numbers.
|
|
26
|
+
*
|
|
27
|
+
* @since 3.18.0
|
|
28
|
+
* @category models
|
|
29
|
+
*/
|
|
30
|
+
export type NodeIndex = number;
|
|
31
|
+
/**
|
|
32
|
+
* Edge index for edge identification using plain numbers.
|
|
33
|
+
*
|
|
34
|
+
* @since 3.18.0
|
|
35
|
+
* @category models
|
|
36
|
+
*/
|
|
37
|
+
export type EdgeIndex = number;
|
|
38
|
+
/**
|
|
39
|
+
* Edge data containing source, target, and user data.
|
|
40
|
+
*
|
|
41
|
+
* @since 3.18.0
|
|
42
|
+
* @category models
|
|
43
|
+
*/
|
|
44
|
+
export declare class Edge<E> extends Data.Class<{
|
|
45
|
+
readonly source: NodeIndex;
|
|
46
|
+
readonly target: NodeIndex;
|
|
47
|
+
readonly data: E;
|
|
48
|
+
}> {
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Graph type for distinguishing directed and undirected graphs.
|
|
52
|
+
*
|
|
53
|
+
* @since 3.18.0
|
|
54
|
+
* @category models
|
|
55
|
+
*/
|
|
56
|
+
export type Kind = "directed" | "undirected";
|
|
57
|
+
/**
|
|
58
|
+
* Graph prototype interface.
|
|
59
|
+
*
|
|
60
|
+
* @since 3.18.0
|
|
61
|
+
* @category models
|
|
62
|
+
*/
|
|
63
|
+
export interface Proto<out N, out E> extends Iterable<readonly [NodeIndex, N]>, Equal.Equal, Pipeable, Inspectable {
|
|
64
|
+
readonly [TypeId]: TypeId;
|
|
65
|
+
readonly nodes: Map<NodeIndex, N>;
|
|
66
|
+
readonly edges: Map<EdgeIndex, Edge<E>>;
|
|
67
|
+
readonly adjacency: Map<NodeIndex, Array<EdgeIndex>>;
|
|
68
|
+
readonly reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
|
|
69
|
+
nextNodeIndex: NodeIndex;
|
|
70
|
+
nextEdgeIndex: EdgeIndex;
|
|
71
|
+
isAcyclic: Option.Option<boolean>;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Immutable graph interface.
|
|
75
|
+
*
|
|
76
|
+
* @since 3.18.0
|
|
77
|
+
* @category models
|
|
78
|
+
*/
|
|
79
|
+
export interface Graph<out N, out E, T extends Kind = "directed"> extends Proto<N, E> {
|
|
80
|
+
readonly type: T;
|
|
81
|
+
readonly mutable: false;
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Mutable graph interface.
|
|
85
|
+
*
|
|
86
|
+
* @since 3.18.0
|
|
87
|
+
* @category models
|
|
88
|
+
*/
|
|
89
|
+
export interface MutableGraph<out N, out E, T extends Kind = "directed"> extends Proto<N, E> {
|
|
90
|
+
readonly type: T;
|
|
91
|
+
readonly mutable: true;
|
|
92
|
+
}
|
|
93
|
+
/**
|
|
94
|
+
* Directed graph type alias.
|
|
95
|
+
*
|
|
96
|
+
* @since 3.18.0
|
|
97
|
+
* @category models
|
|
98
|
+
*/
|
|
99
|
+
export type DirectedGraph<N, E> = Graph<N, E, "directed">;
|
|
100
|
+
/**
|
|
101
|
+
* Undirected graph type alias.
|
|
102
|
+
*
|
|
103
|
+
* @since 3.18.0
|
|
104
|
+
* @category models
|
|
105
|
+
*/
|
|
106
|
+
export type UndirectedGraph<N, E> = Graph<N, E, "undirected">;
|
|
107
|
+
/**
|
|
108
|
+
* Mutable directed graph type alias.
|
|
109
|
+
*
|
|
110
|
+
* @since 3.18.0
|
|
111
|
+
* @category models
|
|
112
|
+
*/
|
|
113
|
+
export type MutableDirectedGraph<N, E> = MutableGraph<N, E, "directed">;
|
|
114
|
+
/**
|
|
115
|
+
* Mutable undirected graph type alias.
|
|
116
|
+
*
|
|
117
|
+
* @since 3.18.0
|
|
118
|
+
* @category models
|
|
119
|
+
*/
|
|
120
|
+
export type MutableUndirectedGraph<N, E> = MutableGraph<N, E, "undirected">;
|
|
121
|
+
/**
|
|
122
|
+
* Creates a directed graph, optionally with initial mutations.
|
|
123
|
+
*
|
|
124
|
+
* @example
|
|
125
|
+
* ```ts
|
|
126
|
+
* import { Graph } from "effect"
|
|
127
|
+
*
|
|
128
|
+
* // Directed graph with initial nodes and edges
|
|
129
|
+
* const graph = Graph.directed<string, string>((mutable) => {
|
|
130
|
+
* const a = Graph.addNode(mutable, "A")
|
|
131
|
+
* const b = Graph.addNode(mutable, "B")
|
|
132
|
+
* const c = Graph.addNode(mutable, "C")
|
|
133
|
+
* Graph.addEdge(mutable, a, b, "A->B")
|
|
134
|
+
* Graph.addEdge(mutable, b, c, "B->C")
|
|
135
|
+
* })
|
|
136
|
+
* ```
|
|
137
|
+
*
|
|
138
|
+
* @since 3.18.0
|
|
139
|
+
* @category constructors
|
|
140
|
+
*/
|
|
141
|
+
export declare const directed: <N, E>(mutate?: (mutable: MutableDirectedGraph<N, E>) => void) => DirectedGraph<N, E>;
|
|
142
|
+
/**
|
|
143
|
+
* Creates an undirected graph, optionally with initial mutations.
|
|
144
|
+
*
|
|
145
|
+
* @example
|
|
146
|
+
* ```ts
|
|
147
|
+
* import { Graph } from "effect"
|
|
148
|
+
*
|
|
149
|
+
* // Undirected graph with initial nodes and edges
|
|
150
|
+
* const graph = Graph.undirected<string, string>((mutable) => {
|
|
151
|
+
* const a = Graph.addNode(mutable, "A")
|
|
152
|
+
* const b = Graph.addNode(mutable, "B")
|
|
153
|
+
* const c = Graph.addNode(mutable, "C")
|
|
154
|
+
* Graph.addEdge(mutable, a, b, "A-B")
|
|
155
|
+
* Graph.addEdge(mutable, b, c, "B-C")
|
|
156
|
+
* })
|
|
157
|
+
* ```
|
|
158
|
+
*
|
|
159
|
+
* @since 3.18.0
|
|
160
|
+
* @category constructors
|
|
161
|
+
*/
|
|
162
|
+
export declare const undirected: <N, E>(mutate?: (mutable: MutableUndirectedGraph<N, E>) => void) => UndirectedGraph<N, E>;
|
|
163
|
+
/**
|
|
164
|
+
* Creates a mutable scope for safe graph mutations by copying the data structure.
|
|
165
|
+
*
|
|
166
|
+
* @example
|
|
167
|
+
* ```ts
|
|
168
|
+
* import { Graph } from "effect"
|
|
169
|
+
*
|
|
170
|
+
* const graph = Graph.directed<string, number>()
|
|
171
|
+
* const mutable = Graph.beginMutation(graph)
|
|
172
|
+
* // Now mutable can be safely modified without affecting original graph
|
|
173
|
+
* ```
|
|
174
|
+
*
|
|
175
|
+
* @since 3.18.0
|
|
176
|
+
* @category mutations
|
|
177
|
+
*/
|
|
178
|
+
export declare const beginMutation: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T>) => MutableGraph<N, E, T>;
|
|
179
|
+
/**
|
|
180
|
+
* Converts a mutable graph back to an immutable graph, ending the mutation scope.
|
|
181
|
+
*
|
|
182
|
+
* @example
|
|
183
|
+
* ```ts
|
|
184
|
+
* import { Graph } from "effect"
|
|
185
|
+
*
|
|
186
|
+
* const graph = Graph.directed<string, number>()
|
|
187
|
+
* const mutable = Graph.beginMutation(graph)
|
|
188
|
+
* // ... perform mutations on mutable ...
|
|
189
|
+
* const newGraph = Graph.endMutation(mutable)
|
|
190
|
+
* ```
|
|
191
|
+
*
|
|
192
|
+
* @since 3.18.0
|
|
193
|
+
* @category mutations
|
|
194
|
+
*/
|
|
195
|
+
export declare const endMutation: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>) => Graph<N, E, T>;
|
|
196
|
+
/**
|
|
197
|
+
* Performs scoped mutations on a graph, automatically managing the mutation lifecycle.
|
|
198
|
+
*
|
|
199
|
+
* @example
|
|
200
|
+
* ```ts
|
|
201
|
+
* import { Graph } from "effect"
|
|
202
|
+
*
|
|
203
|
+
* const graph = Graph.directed<string, number>()
|
|
204
|
+
* const newGraph = Graph.mutate(graph, (mutable) => {
|
|
205
|
+
* // Safe mutations go here
|
|
206
|
+
* // mutable gets automatically converted back to immutable
|
|
207
|
+
* })
|
|
208
|
+
* ```
|
|
209
|
+
*
|
|
210
|
+
* @since 3.18.0
|
|
211
|
+
* @category mutations
|
|
212
|
+
*/
|
|
213
|
+
export declare const mutate: {
|
|
214
|
+
/**
|
|
215
|
+
* Performs scoped mutations on a graph, automatically managing the mutation lifecycle.
|
|
216
|
+
*
|
|
217
|
+
* @example
|
|
218
|
+
* ```ts
|
|
219
|
+
* import { Graph } from "effect"
|
|
220
|
+
*
|
|
221
|
+
* const graph = Graph.directed<string, number>()
|
|
222
|
+
* const newGraph = Graph.mutate(graph, (mutable) => {
|
|
223
|
+
* // Safe mutations go here
|
|
224
|
+
* // mutable gets automatically converted back to immutable
|
|
225
|
+
* })
|
|
226
|
+
* ```
|
|
227
|
+
*
|
|
228
|
+
* @since 3.18.0
|
|
229
|
+
* @category mutations
|
|
230
|
+
*/
|
|
231
|
+
<N, E, T extends Kind = "directed">(f: (mutable: MutableGraph<N, E, T>) => void): (graph: Graph<N, E, T>) => Graph<N, E, T>;
|
|
232
|
+
/**
|
|
233
|
+
* Performs scoped mutations on a graph, automatically managing the mutation lifecycle.
|
|
234
|
+
*
|
|
235
|
+
* @example
|
|
236
|
+
* ```ts
|
|
237
|
+
* import { Graph } from "effect"
|
|
238
|
+
*
|
|
239
|
+
* const graph = Graph.directed<string, number>()
|
|
240
|
+
* const newGraph = Graph.mutate(graph, (mutable) => {
|
|
241
|
+
* // Safe mutations go here
|
|
242
|
+
* // mutable gets automatically converted back to immutable
|
|
243
|
+
* })
|
|
244
|
+
* ```
|
|
245
|
+
*
|
|
246
|
+
* @since 3.18.0
|
|
247
|
+
* @category mutations
|
|
248
|
+
*/
|
|
249
|
+
<N, E, T extends Kind = "directed">(graph: Graph<N, E, T>, f: (mutable: MutableGraph<N, E, T>) => void): Graph<N, E, T>;
|
|
250
|
+
};
|
|
251
|
+
/**
|
|
252
|
+
* Adds a new node to a mutable graph and returns its index.
|
|
253
|
+
*
|
|
254
|
+
* @example
|
|
255
|
+
* ```ts
|
|
256
|
+
* import { Graph } from "effect"
|
|
257
|
+
*
|
|
258
|
+
* const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
259
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
260
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
261
|
+
* console.log(nodeA) // NodeIndex with value 0
|
|
262
|
+
* console.log(nodeB) // NodeIndex with value 1
|
|
263
|
+
* })
|
|
264
|
+
* ```
|
|
265
|
+
*
|
|
266
|
+
* @since 3.18.0
|
|
267
|
+
* @category mutations
|
|
268
|
+
*/
|
|
269
|
+
export declare const addNode: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, data: N) => NodeIndex;
|
|
270
|
+
/**
|
|
271
|
+
* Gets the data associated with a node index, if it exists.
|
|
272
|
+
*
|
|
273
|
+
* @example
|
|
274
|
+
* ```ts
|
|
275
|
+
* import { Graph, Option } from "effect"
|
|
276
|
+
*
|
|
277
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
278
|
+
* Graph.addNode(mutable, "Node A")
|
|
279
|
+
* })
|
|
280
|
+
*
|
|
281
|
+
* const nodeIndex = 0
|
|
282
|
+
* const nodeData = Graph.getNode(graph, nodeIndex)
|
|
283
|
+
*
|
|
284
|
+
* if (Option.isSome(nodeData)) {
|
|
285
|
+
* console.log(nodeData.value) // "Node A"
|
|
286
|
+
* }
|
|
287
|
+
* ```
|
|
288
|
+
*
|
|
289
|
+
* @since 3.18.0
|
|
290
|
+
* @category getters
|
|
291
|
+
*/
|
|
292
|
+
export declare const getNode: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: NodeIndex) => Option.Option<N>;
|
|
293
|
+
/**
|
|
294
|
+
* Checks if a node with the given index exists in the graph.
|
|
295
|
+
*
|
|
296
|
+
* @example
|
|
297
|
+
* ```ts
|
|
298
|
+
* import { Graph } from "effect"
|
|
299
|
+
*
|
|
300
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
301
|
+
* Graph.addNode(mutable, "Node A")
|
|
302
|
+
* })
|
|
303
|
+
*
|
|
304
|
+
* const nodeIndex = 0
|
|
305
|
+
* const exists = Graph.hasNode(graph, nodeIndex)
|
|
306
|
+
* console.log(exists) // true
|
|
307
|
+
*
|
|
308
|
+
* const nonExistentIndex = 999
|
|
309
|
+
* const notExists = Graph.hasNode(graph, nonExistentIndex)
|
|
310
|
+
* console.log(notExists) // false
|
|
311
|
+
* ```
|
|
312
|
+
*
|
|
313
|
+
* @since 3.18.0
|
|
314
|
+
* @category getters
|
|
315
|
+
*/
|
|
316
|
+
export declare const hasNode: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: NodeIndex) => boolean;
|
|
317
|
+
/**
|
|
318
|
+
* Returns the number of nodes in the graph.
|
|
319
|
+
*
|
|
320
|
+
* @example
|
|
321
|
+
* ```ts
|
|
322
|
+
* import { Graph } from "effect"
|
|
323
|
+
*
|
|
324
|
+
* const emptyGraph = Graph.directed<string, number>()
|
|
325
|
+
* console.log(Graph.nodeCount(emptyGraph)) // 0
|
|
326
|
+
*
|
|
327
|
+
* const graphWithNodes = Graph.mutate(emptyGraph, (mutable) => {
|
|
328
|
+
* Graph.addNode(mutable, "Node A")
|
|
329
|
+
* Graph.addNode(mutable, "Node B")
|
|
330
|
+
* Graph.addNode(mutable, "Node C")
|
|
331
|
+
* })
|
|
332
|
+
*
|
|
333
|
+
* console.log(Graph.nodeCount(graphWithNodes)) // 3
|
|
334
|
+
* ```
|
|
335
|
+
*
|
|
336
|
+
* @since 3.18.0
|
|
337
|
+
* @category getters
|
|
338
|
+
*/
|
|
339
|
+
export declare const nodeCount: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => number;
|
|
340
|
+
/**
|
|
341
|
+
* Finds the first node that matches the given predicate.
|
|
342
|
+
*
|
|
343
|
+
* @example
|
|
344
|
+
* ```ts
|
|
345
|
+
* import { Graph, Option } from "effect"
|
|
346
|
+
*
|
|
347
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
348
|
+
* Graph.addNode(mutable, "Node A")
|
|
349
|
+
* Graph.addNode(mutable, "Node B")
|
|
350
|
+
* Graph.addNode(mutable, "Node C")
|
|
351
|
+
* })
|
|
352
|
+
*
|
|
353
|
+
* const result = Graph.findNode(graph, (data) => data.startsWith("Node B"))
|
|
354
|
+
* console.log(result) // Option.some(1)
|
|
355
|
+
*
|
|
356
|
+
* const notFound = Graph.findNode(graph, (data) => data === "Node D")
|
|
357
|
+
* console.log(notFound) // Option.none()
|
|
358
|
+
* ```
|
|
359
|
+
*
|
|
360
|
+
* @since 3.18.0
|
|
361
|
+
* @category getters
|
|
362
|
+
*/
|
|
363
|
+
export declare const findNode: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: N) => boolean) => Option.Option<NodeIndex>;
|
|
364
|
+
/**
|
|
365
|
+
* Finds all nodes that match the given predicate.
|
|
366
|
+
*
|
|
367
|
+
* @example
|
|
368
|
+
* ```ts
|
|
369
|
+
* import { Graph } from "effect"
|
|
370
|
+
*
|
|
371
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
372
|
+
* Graph.addNode(mutable, "Start A")
|
|
373
|
+
* Graph.addNode(mutable, "Node B")
|
|
374
|
+
* Graph.addNode(mutable, "Start C")
|
|
375
|
+
* })
|
|
376
|
+
*
|
|
377
|
+
* const result = Graph.findNodes(graph, (data) => data.startsWith("Start"))
|
|
378
|
+
* console.log(result) // [0, 2]
|
|
379
|
+
*
|
|
380
|
+
* const empty = Graph.findNodes(graph, (data) => data === "Not Found")
|
|
381
|
+
* console.log(empty) // []
|
|
382
|
+
* ```
|
|
383
|
+
*
|
|
384
|
+
* @since 3.18.0
|
|
385
|
+
* @category getters
|
|
386
|
+
*/
|
|
387
|
+
export declare const findNodes: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: N) => boolean) => Array<NodeIndex>;
|
|
388
|
+
/**
|
|
389
|
+
* Finds the first edge that matches the given predicate.
|
|
390
|
+
*
|
|
391
|
+
* @example
|
|
392
|
+
* ```ts
|
|
393
|
+
* import { Graph, Option } from "effect"
|
|
394
|
+
*
|
|
395
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
396
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
397
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
398
|
+
* const nodeC = Graph.addNode(mutable, "Node C")
|
|
399
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 10)
|
|
400
|
+
* Graph.addEdge(mutable, nodeB, nodeC, 20)
|
|
401
|
+
* })
|
|
402
|
+
*
|
|
403
|
+
* const result = Graph.findEdge(graph, (data) => data > 15)
|
|
404
|
+
* console.log(result) // Option.some(1)
|
|
405
|
+
*
|
|
406
|
+
* const notFound = Graph.findEdge(graph, (data) => data > 100)
|
|
407
|
+
* console.log(notFound) // Option.none()
|
|
408
|
+
* ```
|
|
409
|
+
*
|
|
410
|
+
* @since 3.18.0
|
|
411
|
+
* @category getters
|
|
412
|
+
*/
|
|
413
|
+
export declare const findEdge: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean) => Option.Option<EdgeIndex>;
|
|
414
|
+
/**
|
|
415
|
+
* Finds all edges that match the given predicate.
|
|
416
|
+
*
|
|
417
|
+
* @example
|
|
418
|
+
* ```ts
|
|
419
|
+
* import { Graph } from "effect"
|
|
420
|
+
*
|
|
421
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
422
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
423
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
424
|
+
* const nodeC = Graph.addNode(mutable, "Node C")
|
|
425
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 10)
|
|
426
|
+
* Graph.addEdge(mutable, nodeB, nodeC, 20)
|
|
427
|
+
* Graph.addEdge(mutable, nodeC, nodeA, 30)
|
|
428
|
+
* })
|
|
429
|
+
*
|
|
430
|
+
* const result = Graph.findEdges(graph, (data) => data >= 20)
|
|
431
|
+
* console.log(result) // [1, 2]
|
|
432
|
+
*
|
|
433
|
+
* const empty = Graph.findEdges(graph, (data) => data > 100)
|
|
434
|
+
* console.log(empty) // []
|
|
435
|
+
* ```
|
|
436
|
+
*
|
|
437
|
+
* @since 3.18.0
|
|
438
|
+
* @category getters
|
|
439
|
+
*/
|
|
440
|
+
export declare const findEdges: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean) => Array<EdgeIndex>;
|
|
441
|
+
/**
|
|
442
|
+
* Updates a single node's data by applying a transformation function.
|
|
443
|
+
*
|
|
444
|
+
* @example
|
|
445
|
+
* ```ts
|
|
446
|
+
* import { Graph } from "effect"
|
|
447
|
+
*
|
|
448
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
449
|
+
* Graph.addNode(mutable, "Node A")
|
|
450
|
+
* Graph.addNode(mutable, "Node B")
|
|
451
|
+
* Graph.updateNode(mutable, 0, (data) => data.toUpperCase())
|
|
452
|
+
* })
|
|
453
|
+
*
|
|
454
|
+
* const nodeData = Graph.getNode(graph, 0)
|
|
455
|
+
* console.log(nodeData) // Option.some("NODE A")
|
|
456
|
+
* ```
|
|
457
|
+
*
|
|
458
|
+
* @since 3.18.0
|
|
459
|
+
* @category transformations
|
|
460
|
+
*/
|
|
461
|
+
export declare const updateNode: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, index: NodeIndex, f: (data: N) => N) => void;
|
|
462
|
+
/**
|
|
463
|
+
* Updates a single edge's data by applying a transformation function.
|
|
464
|
+
*
|
|
465
|
+
* @example
|
|
466
|
+
* ```ts
|
|
467
|
+
* import { Graph } from "effect"
|
|
468
|
+
*
|
|
469
|
+
* const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
470
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
471
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
472
|
+
* const edgeIndex = Graph.addEdge(mutable, nodeA, nodeB, 10)
|
|
473
|
+
* Graph.updateEdge(mutable, edgeIndex, (data) => data * 2)
|
|
474
|
+
* })
|
|
475
|
+
*
|
|
476
|
+
* const edgeData = Graph.getEdge(result, 0)
|
|
477
|
+
* console.log(edgeData) // Option.some({ source: 0, target: 1, data: 20 })
|
|
478
|
+
* ```
|
|
479
|
+
*
|
|
480
|
+
* @since 3.18.0
|
|
481
|
+
* @category mutations
|
|
482
|
+
*/
|
|
483
|
+
export declare const updateEdge: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, edgeIndex: EdgeIndex, f: (data: E) => E) => void;
|
|
484
|
+
/**
|
|
485
|
+
* Creates a new graph with transformed node data using the provided mapping function.
|
|
486
|
+
*
|
|
487
|
+
* @example
|
|
488
|
+
* ```ts
|
|
489
|
+
* import { Graph } from "effect"
|
|
490
|
+
*
|
|
491
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
492
|
+
* Graph.addNode(mutable, "node a")
|
|
493
|
+
* Graph.addNode(mutable, "node b")
|
|
494
|
+
* Graph.addNode(mutable, "node c")
|
|
495
|
+
* Graph.mapNodes(mutable, (data) => data.toUpperCase())
|
|
496
|
+
* })
|
|
497
|
+
*
|
|
498
|
+
* const nodeData = Graph.getNode(graph, 0)
|
|
499
|
+
* console.log(nodeData) // Option.some("NODE A")
|
|
500
|
+
* ```
|
|
501
|
+
*
|
|
502
|
+
* @since 3.18.0
|
|
503
|
+
* @category transformations
|
|
504
|
+
*/
|
|
505
|
+
export declare const mapNodes: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: N) => N) => void;
|
|
506
|
+
/**
|
|
507
|
+
* Transforms all edge data in a mutable graph using the provided mapping function.
|
|
508
|
+
*
|
|
509
|
+
* @example
|
|
510
|
+
* ```ts
|
|
511
|
+
* import { Graph } from "effect"
|
|
512
|
+
*
|
|
513
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
514
|
+
* const a = Graph.addNode(mutable, "A")
|
|
515
|
+
* const b = Graph.addNode(mutable, "B")
|
|
516
|
+
* const c = Graph.addNode(mutable, "C")
|
|
517
|
+
* Graph.addEdge(mutable, a, b, 10)
|
|
518
|
+
* Graph.addEdge(mutable, b, c, 20)
|
|
519
|
+
* Graph.mapEdges(mutable, (data) => data * 2)
|
|
520
|
+
* })
|
|
521
|
+
*
|
|
522
|
+
* const edgeData = Graph.getEdge(graph, 0)
|
|
523
|
+
* console.log(edgeData) // Option.some({ source: 0, target: 1, data: 20 })
|
|
524
|
+
* ```
|
|
525
|
+
*
|
|
526
|
+
* @since 3.18.0
|
|
527
|
+
* @category transformations
|
|
528
|
+
*/
|
|
529
|
+
export declare const mapEdges: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: E) => E) => void;
|
|
530
|
+
/**
|
|
531
|
+
* Reverses all edge directions in a mutable graph by swapping source and target nodes.
|
|
532
|
+
*
|
|
533
|
+
* @example
|
|
534
|
+
* ```ts
|
|
535
|
+
* import { Graph } from "effect"
|
|
536
|
+
*
|
|
537
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
538
|
+
* const a = Graph.addNode(mutable, "A")
|
|
539
|
+
* const b = Graph.addNode(mutable, "B")
|
|
540
|
+
* const c = Graph.addNode(mutable, "C")
|
|
541
|
+
* Graph.addEdge(mutable, a, b, 1) // A -> B
|
|
542
|
+
* Graph.addEdge(mutable, b, c, 2) // B -> C
|
|
543
|
+
* Graph.reverse(mutable) // Now B -> A, C -> B
|
|
544
|
+
* })
|
|
545
|
+
*
|
|
546
|
+
* const edge0 = Graph.getEdge(graph, 0)
|
|
547
|
+
* console.log(edge0) // Option.some({ source: 1, target: 0, data: 1 }) - B -> A
|
|
548
|
+
* ```
|
|
549
|
+
*
|
|
550
|
+
* @since 3.18.0
|
|
551
|
+
* @category transformations
|
|
552
|
+
*/
|
|
553
|
+
export declare const reverse: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>) => void;
|
|
554
|
+
/**
|
|
555
|
+
* Filters and optionally transforms nodes in a mutable graph using a predicate function.
|
|
556
|
+
* Nodes that return Option.none are removed along with all their connected edges.
|
|
557
|
+
*
|
|
558
|
+
* @example
|
|
559
|
+
* ```ts
|
|
560
|
+
* import { Graph, Option } from "effect"
|
|
561
|
+
*
|
|
562
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
563
|
+
* const a = Graph.addNode(mutable, "active")
|
|
564
|
+
* const b = Graph.addNode(mutable, "inactive")
|
|
565
|
+
* const c = Graph.addNode(mutable, "active")
|
|
566
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
567
|
+
* Graph.addEdge(mutable, b, c, 2)
|
|
568
|
+
*
|
|
569
|
+
* // Keep only "active" nodes and transform to uppercase
|
|
570
|
+
* Graph.filterMapNodes(mutable, (data) =>
|
|
571
|
+
* data === "active" ? Option.some(data.toUpperCase()) : Option.none()
|
|
572
|
+
* )
|
|
573
|
+
* })
|
|
574
|
+
*
|
|
575
|
+
* console.log(Graph.nodeCount(graph)) // 2 (only "active" nodes remain)
|
|
576
|
+
* ```
|
|
577
|
+
*
|
|
578
|
+
* @since 3.18.0
|
|
579
|
+
* @category transformations
|
|
580
|
+
*/
|
|
581
|
+
export declare const filterMapNodes: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: N) => Option.Option<N>) => void;
|
|
582
|
+
/**
|
|
583
|
+
* Filters and optionally transforms edges in a mutable graph using a predicate function.
|
|
584
|
+
* Edges that return Option.none are removed from the graph.
|
|
585
|
+
*
|
|
586
|
+
* @example
|
|
587
|
+
* ```ts
|
|
588
|
+
* import { Graph, Option } from "effect"
|
|
589
|
+
*
|
|
590
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
591
|
+
* const a = Graph.addNode(mutable, "A")
|
|
592
|
+
* const b = Graph.addNode(mutable, "B")
|
|
593
|
+
* const c = Graph.addNode(mutable, "C")
|
|
594
|
+
* Graph.addEdge(mutable, a, b, 5)
|
|
595
|
+
* Graph.addEdge(mutable, b, c, 15)
|
|
596
|
+
* Graph.addEdge(mutable, c, a, 25)
|
|
597
|
+
*
|
|
598
|
+
* // Keep only edges with weight >= 10 and double their weight
|
|
599
|
+
* Graph.filterMapEdges(mutable, (data) =>
|
|
600
|
+
* data >= 10 ? Option.some(data * 2) : Option.none()
|
|
601
|
+
* )
|
|
602
|
+
* })
|
|
603
|
+
*
|
|
604
|
+
* console.log(Graph.edgeCount(graph)) // 2 (edges with weight 5 removed)
|
|
605
|
+
* ```
|
|
606
|
+
*
|
|
607
|
+
* @since 3.18.0
|
|
608
|
+
* @category transformations
|
|
609
|
+
*/
|
|
610
|
+
export declare const filterMapEdges: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: E) => Option.Option<E>) => void;
|
|
611
|
+
/**
|
|
612
|
+
* Filters nodes by removing those that don't match the predicate.
|
|
613
|
+
* This function modifies the mutable graph in place.
|
|
614
|
+
*
|
|
615
|
+
* @example
|
|
616
|
+
* ```ts
|
|
617
|
+
* import { Graph } from "effect"
|
|
618
|
+
*
|
|
619
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
620
|
+
* Graph.addNode(mutable, "active")
|
|
621
|
+
* Graph.addNode(mutable, "inactive")
|
|
622
|
+
* Graph.addNode(mutable, "pending")
|
|
623
|
+
* Graph.addNode(mutable, "active")
|
|
624
|
+
*
|
|
625
|
+
* // Keep only "active" nodes
|
|
626
|
+
* Graph.filterNodes(mutable, (data) => data === "active")
|
|
627
|
+
* })
|
|
628
|
+
*
|
|
629
|
+
* console.log(Graph.nodeCount(graph)) // 2 (only "active" nodes remain)
|
|
630
|
+
* ```
|
|
631
|
+
*
|
|
632
|
+
* @since 3.18.0
|
|
633
|
+
* @category transformations
|
|
634
|
+
*/
|
|
635
|
+
export declare const filterNodes: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, predicate: (data: N) => boolean) => void;
|
|
636
|
+
/**
|
|
637
|
+
* Filters edges by removing those that don't match the predicate.
|
|
638
|
+
* This function modifies the mutable graph in place.
|
|
639
|
+
*
|
|
640
|
+
* @example
|
|
641
|
+
* ```ts
|
|
642
|
+
* import { Graph } from "effect"
|
|
643
|
+
*
|
|
644
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
645
|
+
* const a = Graph.addNode(mutable, "A")
|
|
646
|
+
* const b = Graph.addNode(mutable, "B")
|
|
647
|
+
* const c = Graph.addNode(mutable, "C")
|
|
648
|
+
*
|
|
649
|
+
* Graph.addEdge(mutable, a, b, 5)
|
|
650
|
+
* Graph.addEdge(mutable, b, c, 15)
|
|
651
|
+
* Graph.addEdge(mutable, c, a, 25)
|
|
652
|
+
*
|
|
653
|
+
* // Keep only edges with weight >= 10
|
|
654
|
+
* Graph.filterEdges(mutable, (data) => data >= 10)
|
|
655
|
+
* })
|
|
656
|
+
*
|
|
657
|
+
* console.log(Graph.edgeCount(graph)) // 2 (edge with weight 5 removed)
|
|
658
|
+
* ```
|
|
659
|
+
*
|
|
660
|
+
* @since 3.18.0
|
|
661
|
+
* @category transformations
|
|
662
|
+
*/
|
|
663
|
+
export declare const filterEdges: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, predicate: (data: E) => boolean) => void;
|
|
664
|
+
/**
|
|
665
|
+
* Adds a new edge to a mutable graph and returns its index.
|
|
666
|
+
*
|
|
667
|
+
* @example
|
|
668
|
+
* ```ts
|
|
669
|
+
* import { Graph } from "effect"
|
|
670
|
+
*
|
|
671
|
+
* const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
672
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
673
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
674
|
+
* const edge = Graph.addEdge(mutable, nodeA, nodeB, 42)
|
|
675
|
+
* console.log(edge) // EdgeIndex with value 0
|
|
676
|
+
* })
|
|
677
|
+
* ```
|
|
678
|
+
*
|
|
679
|
+
* @since 3.18.0
|
|
680
|
+
* @category mutations
|
|
681
|
+
*/
|
|
682
|
+
export declare const addEdge: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E) => EdgeIndex;
|
|
683
|
+
/**
|
|
684
|
+
* Removes a node and all its incident edges from a mutable graph.
|
|
685
|
+
*
|
|
686
|
+
* @example
|
|
687
|
+
* ```ts
|
|
688
|
+
* import { Graph } from "effect"
|
|
689
|
+
*
|
|
690
|
+
* const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
691
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
692
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
693
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 42)
|
|
694
|
+
*
|
|
695
|
+
* // Remove nodeA and all edges connected to it
|
|
696
|
+
* Graph.removeNode(mutable, nodeA)
|
|
697
|
+
* })
|
|
698
|
+
* ```
|
|
699
|
+
*
|
|
700
|
+
* @since 3.18.0
|
|
701
|
+
* @category mutations
|
|
702
|
+
*/
|
|
703
|
+
export declare const removeNode: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, nodeIndex: NodeIndex) => void;
|
|
704
|
+
/**
|
|
705
|
+
* Removes an edge from a mutable graph.
|
|
706
|
+
*
|
|
707
|
+
* @example
|
|
708
|
+
* ```ts
|
|
709
|
+
* import { Graph } from "effect"
|
|
710
|
+
*
|
|
711
|
+
* const result = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
712
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
713
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
714
|
+
* const edge = Graph.addEdge(mutable, nodeA, nodeB, 42)
|
|
715
|
+
*
|
|
716
|
+
* // Remove the edge
|
|
717
|
+
* Graph.removeEdge(mutable, edge)
|
|
718
|
+
* })
|
|
719
|
+
* ```
|
|
720
|
+
*
|
|
721
|
+
* @since 3.18.0
|
|
722
|
+
* @category mutations
|
|
723
|
+
*/
|
|
724
|
+
export declare const removeEdge: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, edgeIndex: EdgeIndex) => void;
|
|
725
|
+
/**
|
|
726
|
+
* Gets the edge data associated with an edge index, if it exists.
|
|
727
|
+
*
|
|
728
|
+
* @example
|
|
729
|
+
* ```ts
|
|
730
|
+
* import { Graph, Option } from "effect"
|
|
731
|
+
*
|
|
732
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
733
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
734
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
735
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 42)
|
|
736
|
+
* })
|
|
737
|
+
*
|
|
738
|
+
* const edgeIndex = 0
|
|
739
|
+
* const edgeData = Graph.getEdge(graph, edgeIndex)
|
|
740
|
+
*
|
|
741
|
+
* if (Option.isSome(edgeData)) {
|
|
742
|
+
* console.log(edgeData.value.data) // 42
|
|
743
|
+
* console.log(edgeData.value.source) // NodeIndex(0)
|
|
744
|
+
* console.log(edgeData.value.target) // NodeIndex(1)
|
|
745
|
+
* }
|
|
746
|
+
* ```
|
|
747
|
+
*
|
|
748
|
+
* @since 3.18.0
|
|
749
|
+
* @category getters
|
|
750
|
+
*/
|
|
751
|
+
export declare const getEdge: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, edgeIndex: EdgeIndex) => Option.Option<Edge<E>>;
|
|
752
|
+
/**
|
|
753
|
+
* Checks if an edge exists between two nodes in the graph.
|
|
754
|
+
*
|
|
755
|
+
* @example
|
|
756
|
+
* ```ts
|
|
757
|
+
* import { Graph } from "effect"
|
|
758
|
+
*
|
|
759
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
760
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
761
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
762
|
+
* const nodeC = Graph.addNode(mutable, "Node C")
|
|
763
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 42)
|
|
764
|
+
* })
|
|
765
|
+
*
|
|
766
|
+
* const nodeA = 0
|
|
767
|
+
* const nodeB = 1
|
|
768
|
+
* const nodeC = 2
|
|
769
|
+
*
|
|
770
|
+
* const hasAB = Graph.hasEdge(graph, nodeA, nodeB)
|
|
771
|
+
* console.log(hasAB) // true
|
|
772
|
+
*
|
|
773
|
+
* const hasAC = Graph.hasEdge(graph, nodeA, nodeC)
|
|
774
|
+
* console.log(hasAC) // false
|
|
775
|
+
* ```
|
|
776
|
+
*
|
|
777
|
+
* @since 3.18.0
|
|
778
|
+
* @category getters
|
|
779
|
+
*/
|
|
780
|
+
export declare const hasEdge: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex) => boolean;
|
|
781
|
+
/**
|
|
782
|
+
* Returns the number of edges in the graph.
|
|
783
|
+
*
|
|
784
|
+
* @example
|
|
785
|
+
* ```ts
|
|
786
|
+
* import { Graph } from "effect"
|
|
787
|
+
*
|
|
788
|
+
* const emptyGraph = Graph.directed<string, number>()
|
|
789
|
+
* console.log(Graph.edgeCount(emptyGraph)) // 0
|
|
790
|
+
*
|
|
791
|
+
* const graphWithEdges = Graph.mutate(emptyGraph, (mutable) => {
|
|
792
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
793
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
794
|
+
* const nodeC = Graph.addNode(mutable, "Node C")
|
|
795
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 1)
|
|
796
|
+
* Graph.addEdge(mutable, nodeB, nodeC, 2)
|
|
797
|
+
* Graph.addEdge(mutable, nodeC, nodeA, 3)
|
|
798
|
+
* })
|
|
799
|
+
*
|
|
800
|
+
* console.log(Graph.edgeCount(graphWithEdges)) // 3
|
|
801
|
+
* ```
|
|
802
|
+
*
|
|
803
|
+
* @since 3.18.0
|
|
804
|
+
* @category getters
|
|
805
|
+
*/
|
|
806
|
+
export declare const edgeCount: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => number;
|
|
807
|
+
/**
|
|
808
|
+
* Returns the neighboring nodes (targets of outgoing edges) for a given node.
|
|
809
|
+
*
|
|
810
|
+
* @example
|
|
811
|
+
* ```ts
|
|
812
|
+
* import { Graph } from "effect"
|
|
813
|
+
*
|
|
814
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
815
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
816
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
817
|
+
* const nodeC = Graph.addNode(mutable, "Node C")
|
|
818
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 1)
|
|
819
|
+
* Graph.addEdge(mutable, nodeA, nodeC, 2)
|
|
820
|
+
* })
|
|
821
|
+
*
|
|
822
|
+
* const nodeA = 0
|
|
823
|
+
* const nodeB = 1
|
|
824
|
+
* const nodeC = 2
|
|
825
|
+
*
|
|
826
|
+
* const neighborsA = Graph.neighbors(graph, nodeA)
|
|
827
|
+
* console.log(neighborsA) // [NodeIndex(1), NodeIndex(2)]
|
|
828
|
+
*
|
|
829
|
+
* const neighborsB = Graph.neighbors(graph, nodeB)
|
|
830
|
+
* console.log(neighborsB) // []
|
|
831
|
+
* ```
|
|
832
|
+
*
|
|
833
|
+
* @since 3.18.0
|
|
834
|
+
* @category getters
|
|
835
|
+
*/
|
|
836
|
+
export declare const neighbors: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: NodeIndex) => Array<NodeIndex>;
|
|
837
|
+
/**
|
|
838
|
+
* Get neighbors of a node in a specific direction for bidirectional traversal.
|
|
839
|
+
*
|
|
840
|
+
* @example
|
|
841
|
+
* ```ts
|
|
842
|
+
* import { Graph } from "effect"
|
|
843
|
+
*
|
|
844
|
+
* const graph = Graph.directed<string, string>((mutable) => {
|
|
845
|
+
* const a = Graph.addNode(mutable, "A")
|
|
846
|
+
* const b = Graph.addNode(mutable, "B")
|
|
847
|
+
* Graph.addEdge(mutable, a, b, "A->B")
|
|
848
|
+
* })
|
|
849
|
+
*
|
|
850
|
+
* const nodeA = 0
|
|
851
|
+
* const nodeB = 1
|
|
852
|
+
*
|
|
853
|
+
* // Get outgoing neighbors (nodes that nodeA points to)
|
|
854
|
+
* const outgoing = Graph.neighborsDirected(graph, nodeA, "outgoing")
|
|
855
|
+
*
|
|
856
|
+
* // Get incoming neighbors (nodes that point to nodeB)
|
|
857
|
+
* const incoming = Graph.neighborsDirected(graph, nodeB, "incoming")
|
|
858
|
+
* ```
|
|
859
|
+
*
|
|
860
|
+
* @since 3.18.0
|
|
861
|
+
* @category queries
|
|
862
|
+
*/
|
|
863
|
+
export declare const neighborsDirected: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: NodeIndex, direction: Direction) => Array<NodeIndex>;
|
|
864
|
+
/**
|
|
865
|
+
* Exports a graph to GraphViz DOT format for visualization.
|
|
866
|
+
*
|
|
867
|
+
* @example
|
|
868
|
+
* ```ts
|
|
869
|
+
* import { Graph } from "effect"
|
|
870
|
+
*
|
|
871
|
+
* const graph = Graph.mutate(Graph.directed<string, number>(), (mutable) => {
|
|
872
|
+
* const nodeA = Graph.addNode(mutable, "Node A")
|
|
873
|
+
* const nodeB = Graph.addNode(mutable, "Node B")
|
|
874
|
+
* const nodeC = Graph.addNode(mutable, "Node C")
|
|
875
|
+
* Graph.addEdge(mutable, nodeA, nodeB, 1)
|
|
876
|
+
* Graph.addEdge(mutable, nodeB, nodeC, 2)
|
|
877
|
+
* Graph.addEdge(mutable, nodeC, nodeA, 3)
|
|
878
|
+
* })
|
|
879
|
+
*
|
|
880
|
+
* const dot = Graph.toGraphViz(graph)
|
|
881
|
+
* console.log(dot)
|
|
882
|
+
* // digraph G {
|
|
883
|
+
* // "0" [label="Node A"];
|
|
884
|
+
* // "1" [label="Node B"];
|
|
885
|
+
* // "2" [label="Node C"];
|
|
886
|
+
* // "0" -> "1" [label="1"];
|
|
887
|
+
* // "1" -> "2" [label="2"];
|
|
888
|
+
* // "2" -> "0" [label="3"];
|
|
889
|
+
* // }
|
|
890
|
+
* ```
|
|
891
|
+
*
|
|
892
|
+
* @since 3.18.0
|
|
893
|
+
* @category utils
|
|
894
|
+
*/
|
|
895
|
+
export declare const toGraphViz: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, options?: {
|
|
896
|
+
readonly nodeLabel?: (data: N) => string;
|
|
897
|
+
readonly edgeLabel?: (data: E) => string;
|
|
898
|
+
readonly graphName?: string;
|
|
899
|
+
}) => string;
|
|
900
|
+
/**
|
|
901
|
+
* Direction for graph traversal, indicating which edges to follow.
|
|
902
|
+
*
|
|
903
|
+
* @example
|
|
904
|
+
* ```ts
|
|
905
|
+
* import { Graph } from "effect"
|
|
906
|
+
*
|
|
907
|
+
* const graph = Graph.directed<string, string>((mutable) => {
|
|
908
|
+
* const a = Graph.addNode(mutable, "A")
|
|
909
|
+
* const b = Graph.addNode(mutable, "B")
|
|
910
|
+
* Graph.addEdge(mutable, a, b, "A->B")
|
|
911
|
+
* })
|
|
912
|
+
*
|
|
913
|
+
* // Follow outgoing edges (normal direction)
|
|
914
|
+
* const outgoingNodes = Array.from(Graph.indices(Graph.dfs(graph, { startNodes: [0], direction: "outgoing" })))
|
|
915
|
+
*
|
|
916
|
+
* // Follow incoming edges (reverse direction)
|
|
917
|
+
* const incomingNodes = Array.from(Graph.indices(Graph.dfs(graph, { startNodes: [1], direction: "incoming" })))
|
|
918
|
+
* ```
|
|
919
|
+
*
|
|
920
|
+
* @since 3.18.0
|
|
921
|
+
* @category models
|
|
922
|
+
*/
|
|
923
|
+
export type Direction = "outgoing" | "incoming";
|
|
924
|
+
/**
|
|
925
|
+
* Checks if the graph is acyclic (contains no cycles).
|
|
926
|
+
*
|
|
927
|
+
* Uses depth-first search to detect back edges, which indicate cycles.
|
|
928
|
+
* For directed graphs, any back edge creates a cycle. For undirected graphs,
|
|
929
|
+
* a back edge that doesn't go to the immediate parent creates a cycle.
|
|
930
|
+
*
|
|
931
|
+
* @example
|
|
932
|
+
* ```ts
|
|
933
|
+
* import { Graph } from "effect"
|
|
934
|
+
*
|
|
935
|
+
* // Acyclic directed graph (DAG)
|
|
936
|
+
* const dag = Graph.directed<string, string>((mutable) => {
|
|
937
|
+
* const a = Graph.addNode(mutable, "A")
|
|
938
|
+
* const b = Graph.addNode(mutable, "B")
|
|
939
|
+
* const c = Graph.addNode(mutable, "C")
|
|
940
|
+
* Graph.addEdge(mutable, a, b, "A->B")
|
|
941
|
+
* Graph.addEdge(mutable, b, c, "B->C")
|
|
942
|
+
* })
|
|
943
|
+
* console.log(Graph.isAcyclic(dag)) // true
|
|
944
|
+
*
|
|
945
|
+
* // Cyclic directed graph
|
|
946
|
+
* const cyclic = Graph.directed<string, string>((mutable) => {
|
|
947
|
+
* const a = Graph.addNode(mutable, "A")
|
|
948
|
+
* const b = Graph.addNode(mutable, "B")
|
|
949
|
+
* Graph.addEdge(mutable, a, b, "A->B")
|
|
950
|
+
* Graph.addEdge(mutable, b, a, "B->A") // Creates cycle
|
|
951
|
+
* })
|
|
952
|
+
* console.log(Graph.isAcyclic(cyclic)) // false
|
|
953
|
+
* ```
|
|
954
|
+
*
|
|
955
|
+
* @since 3.18.0
|
|
956
|
+
* @category algorithms
|
|
957
|
+
*/
|
|
958
|
+
export declare const isAcyclic: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => boolean;
|
|
959
|
+
/**
|
|
960
|
+
* Checks if an undirected graph is bipartite.
|
|
961
|
+
*
|
|
962
|
+
* A bipartite graph is one whose vertices can be divided into two disjoint sets
|
|
963
|
+
* such that no two vertices within the same set are adjacent. Uses BFS coloring
|
|
964
|
+
* to determine bipartiteness.
|
|
965
|
+
*
|
|
966
|
+
* @example
|
|
967
|
+
* ```ts
|
|
968
|
+
* import { Graph } from "effect"
|
|
969
|
+
*
|
|
970
|
+
* // Bipartite graph (alternating coloring possible)
|
|
971
|
+
* const bipartite = Graph.undirected<string, string>((mutable) => {
|
|
972
|
+
* const a = Graph.addNode(mutable, "A")
|
|
973
|
+
* const b = Graph.addNode(mutable, "B")
|
|
974
|
+
* const c = Graph.addNode(mutable, "C")
|
|
975
|
+
* const d = Graph.addNode(mutable, "D")
|
|
976
|
+
* Graph.addEdge(mutable, a, b, "edge") // Set 1: {A, C}, Set 2: {B, D}
|
|
977
|
+
* Graph.addEdge(mutable, b, c, "edge")
|
|
978
|
+
* Graph.addEdge(mutable, c, d, "edge")
|
|
979
|
+
* })
|
|
980
|
+
* console.log(Graph.isBipartite(bipartite)) // true
|
|
981
|
+
*
|
|
982
|
+
* // Non-bipartite graph (odd cycle)
|
|
983
|
+
* const triangle = Graph.undirected<string, string>((mutable) => {
|
|
984
|
+
* const a = Graph.addNode(mutable, "A")
|
|
985
|
+
* const b = Graph.addNode(mutable, "B")
|
|
986
|
+
* const c = Graph.addNode(mutable, "C")
|
|
987
|
+
* Graph.addEdge(mutable, a, b, "edge")
|
|
988
|
+
* Graph.addEdge(mutable, b, c, "edge")
|
|
989
|
+
* Graph.addEdge(mutable, c, a, "edge") // Triangle (3-cycle)
|
|
990
|
+
* })
|
|
991
|
+
* console.log(Graph.isBipartite(triangle)) // false
|
|
992
|
+
* ```
|
|
993
|
+
*
|
|
994
|
+
* @since 3.18.0
|
|
995
|
+
* @category algorithms
|
|
996
|
+
*/
|
|
997
|
+
export declare const isBipartite: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => boolean;
|
|
998
|
+
/**
|
|
999
|
+
* Find connected components in an undirected graph.
|
|
1000
|
+
* Each component is represented as an array of node indices.
|
|
1001
|
+
*
|
|
1002
|
+
* @example
|
|
1003
|
+
* ```ts
|
|
1004
|
+
* import { Graph } from "effect"
|
|
1005
|
+
*
|
|
1006
|
+
* const graph = Graph.undirected<string, string>((mutable) => {
|
|
1007
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1008
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1009
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1010
|
+
* const d = Graph.addNode(mutable, "D")
|
|
1011
|
+
* Graph.addEdge(mutable, a, b, "edge") // Component 1: A-B
|
|
1012
|
+
* Graph.addEdge(mutable, c, d, "edge") // Component 2: C-D
|
|
1013
|
+
* })
|
|
1014
|
+
*
|
|
1015
|
+
* const components = Graph.connectedComponents(graph)
|
|
1016
|
+
* console.log(components) // [[0, 1], [2, 3]]
|
|
1017
|
+
* ```
|
|
1018
|
+
*
|
|
1019
|
+
* @since 3.18.0
|
|
1020
|
+
* @category algorithms
|
|
1021
|
+
*/
|
|
1022
|
+
export declare const connectedComponents: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => Array<Array<NodeIndex>>;
|
|
1023
|
+
/**
|
|
1024
|
+
* Find strongly connected components in a directed graph using Kosaraju's algorithm.
|
|
1025
|
+
* Each SCC is represented as an array of node indices.
|
|
1026
|
+
*
|
|
1027
|
+
* @example
|
|
1028
|
+
* ```ts
|
|
1029
|
+
* import { Graph } from "effect"
|
|
1030
|
+
*
|
|
1031
|
+
* const graph = Graph.directed<string, string>((mutable) => {
|
|
1032
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1033
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1034
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1035
|
+
* Graph.addEdge(mutable, a, b, "A->B")
|
|
1036
|
+
* Graph.addEdge(mutable, b, c, "B->C")
|
|
1037
|
+
* Graph.addEdge(mutable, c, a, "C->A") // Creates SCC: A-B-C
|
|
1038
|
+
* })
|
|
1039
|
+
*
|
|
1040
|
+
* const sccs = Graph.stronglyConnectedComponents(graph)
|
|
1041
|
+
* console.log(sccs) // [[0, 1, 2]]
|
|
1042
|
+
* ```
|
|
1043
|
+
*
|
|
1044
|
+
* @since 3.18.0
|
|
1045
|
+
* @category algorithms
|
|
1046
|
+
*/
|
|
1047
|
+
export declare const stronglyConnectedComponents: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Array<Array<NodeIndex>>;
|
|
1048
|
+
/**
|
|
1049
|
+
* Result of a shortest path computation containing the path and total distance.
|
|
1050
|
+
*
|
|
1051
|
+
* @since 3.18.0
|
|
1052
|
+
* @category models
|
|
1053
|
+
*/
|
|
1054
|
+
export interface PathResult<E> {
|
|
1055
|
+
readonly path: Array<NodeIndex>;
|
|
1056
|
+
readonly distance: number;
|
|
1057
|
+
readonly edgeWeights: Array<E>;
|
|
1058
|
+
}
|
|
1059
|
+
/**
|
|
1060
|
+
* Find the shortest path between two nodes using Dijkstra's algorithm.
|
|
1061
|
+
*
|
|
1062
|
+
* Dijkstra's algorithm works with non-negative edge weights and finds the shortest
|
|
1063
|
+
* path from a source node to a target node in O((V + E) log V) time complexity.
|
|
1064
|
+
*
|
|
1065
|
+
* @example
|
|
1066
|
+
* ```ts
|
|
1067
|
+
* import { Graph, Option } from "effect"
|
|
1068
|
+
*
|
|
1069
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1070
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1071
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1072
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1073
|
+
* Graph.addEdge(mutable, a, b, 5)
|
|
1074
|
+
* Graph.addEdge(mutable, a, c, 10)
|
|
1075
|
+
* Graph.addEdge(mutable, b, c, 2)
|
|
1076
|
+
* })
|
|
1077
|
+
*
|
|
1078
|
+
* const result = Graph.dijkstra(graph, 0, 2, (edgeData) => edgeData)
|
|
1079
|
+
* if (Option.isSome(result)) {
|
|
1080
|
+
* console.log(result.value.path) // [0, 1, 2] - shortest path A->B->C
|
|
1081
|
+
* console.log(result.value.distance) // 7 - total distance
|
|
1082
|
+
* }
|
|
1083
|
+
* ```
|
|
1084
|
+
*
|
|
1085
|
+
* @since 3.18.0
|
|
1086
|
+
* @category algorithms
|
|
1087
|
+
*/
|
|
1088
|
+
export declare const dijkstra: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, edgeWeight: (edgeData: E) => number) => Option.Option<PathResult<E>>;
|
|
1089
|
+
/**
|
|
1090
|
+
* Result of all-pairs shortest path computation.
|
|
1091
|
+
*
|
|
1092
|
+
* @since 3.18.0
|
|
1093
|
+
* @category models
|
|
1094
|
+
*/
|
|
1095
|
+
export interface AllPairsResult<E> {
|
|
1096
|
+
readonly distances: Map<NodeIndex, Map<NodeIndex, number>>;
|
|
1097
|
+
readonly paths: Map<NodeIndex, Map<NodeIndex, Array<NodeIndex> | null>>;
|
|
1098
|
+
readonly edgeWeights: Map<NodeIndex, Map<NodeIndex, Array<E>>>;
|
|
1099
|
+
}
|
|
1100
|
+
/**
|
|
1101
|
+
* Find shortest paths between all pairs of nodes using Floyd-Warshall algorithm.
|
|
1102
|
+
*
|
|
1103
|
+
* Floyd-Warshall algorithm computes shortest paths between all pairs of nodes in O(V³) time.
|
|
1104
|
+
* It can handle negative edge weights and detect negative cycles.
|
|
1105
|
+
*
|
|
1106
|
+
* @example
|
|
1107
|
+
* ```ts
|
|
1108
|
+
* import { Graph } from "effect"
|
|
1109
|
+
*
|
|
1110
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1111
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1112
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1113
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1114
|
+
* Graph.addEdge(mutable, a, b, 3)
|
|
1115
|
+
* Graph.addEdge(mutable, b, c, 2)
|
|
1116
|
+
* Graph.addEdge(mutable, a, c, 7)
|
|
1117
|
+
* })
|
|
1118
|
+
*
|
|
1119
|
+
* const result = Graph.floydWarshall(graph, (edgeData) => edgeData)
|
|
1120
|
+
* const distanceAToC = result.distances.get(0)?.get(2) // 5 (A->B->C)
|
|
1121
|
+
* const pathAToC = result.paths.get(0)?.get(2) // [0, 1, 2]
|
|
1122
|
+
* ```
|
|
1123
|
+
*
|
|
1124
|
+
* @since 3.18.0
|
|
1125
|
+
* @category algorithms
|
|
1126
|
+
*/
|
|
1127
|
+
export declare const floydWarshall: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, edgeWeight: (edgeData: E) => number) => AllPairsResult<E>;
|
|
1128
|
+
/**
|
|
1129
|
+
* Find the shortest path between two nodes using A* pathfinding algorithm.
|
|
1130
|
+
*
|
|
1131
|
+
* A* is an extension of Dijkstra's algorithm that uses a heuristic function to guide
|
|
1132
|
+
* the search towards the target, potentially finding paths faster than Dijkstra's.
|
|
1133
|
+
* The heuristic must be admissible (never overestimate the actual cost).
|
|
1134
|
+
*
|
|
1135
|
+
* @example
|
|
1136
|
+
* ```ts
|
|
1137
|
+
* import { Graph, Option } from "effect"
|
|
1138
|
+
*
|
|
1139
|
+
* const graph = Graph.directed<{x: number, y: number}, number>((mutable) => {
|
|
1140
|
+
* const a = Graph.addNode(mutable, {x: 0, y: 0})
|
|
1141
|
+
* const b = Graph.addNode(mutable, {x: 1, y: 0})
|
|
1142
|
+
* const c = Graph.addNode(mutable, {x: 2, y: 0})
|
|
1143
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1144
|
+
* Graph.addEdge(mutable, b, c, 1)
|
|
1145
|
+
* })
|
|
1146
|
+
*
|
|
1147
|
+
* // Manhattan distance heuristic
|
|
1148
|
+
* const heuristic = (nodeData: {x: number, y: number}, targetData: {x: number, y: number}) =>
|
|
1149
|
+
* Math.abs(nodeData.x - targetData.x) + Math.abs(nodeData.y - targetData.y)
|
|
1150
|
+
*
|
|
1151
|
+
* const result = Graph.astar(graph, 0, 2, (edgeData) => edgeData, heuristic)
|
|
1152
|
+
* if (Option.isSome(result)) {
|
|
1153
|
+
* console.log(result.value.path) // [0, 1, 2] - shortest path
|
|
1154
|
+
* console.log(result.value.distance) // 2 - total distance
|
|
1155
|
+
* }
|
|
1156
|
+
* ```
|
|
1157
|
+
*
|
|
1158
|
+
* @since 3.18.0
|
|
1159
|
+
* @category algorithms
|
|
1160
|
+
*/
|
|
1161
|
+
export declare const astar: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, edgeWeight: (edgeData: E) => number, heuristic: (sourceNodeData: N, targetNodeData: N) => number) => Option.Option<PathResult<E>>;
|
|
1162
|
+
/**
|
|
1163
|
+
* Find the shortest path between two nodes using Bellman-Ford algorithm.
|
|
1164
|
+
*
|
|
1165
|
+
* Bellman-Ford algorithm can handle negative edge weights and detects negative cycles.
|
|
1166
|
+
* It has O(VE) time complexity, slower than Dijkstra's but more versatile.
|
|
1167
|
+
* Returns Option.none() if a negative cycle is detected that affects the path.
|
|
1168
|
+
*
|
|
1169
|
+
* @example
|
|
1170
|
+
* ```ts
|
|
1171
|
+
* import { Graph, Option } from "effect"
|
|
1172
|
+
*
|
|
1173
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1174
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1175
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1176
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1177
|
+
* Graph.addEdge(mutable, a, b, -1) // Negative weight allowed
|
|
1178
|
+
* Graph.addEdge(mutable, b, c, 3)
|
|
1179
|
+
* Graph.addEdge(mutable, a, c, 5)
|
|
1180
|
+
* })
|
|
1181
|
+
*
|
|
1182
|
+
* const result = Graph.bellmanFord(graph, 0, 2, (edgeData) => edgeData)
|
|
1183
|
+
* if (Option.isSome(result)) {
|
|
1184
|
+
* console.log(result.value.path) // [0, 1, 2] - shortest path A->B->C
|
|
1185
|
+
* console.log(result.value.distance) // 2 - total distance
|
|
1186
|
+
* }
|
|
1187
|
+
* ```
|
|
1188
|
+
*
|
|
1189
|
+
* @since 3.18.0
|
|
1190
|
+
* @category algorithms
|
|
1191
|
+
*/
|
|
1192
|
+
export declare const bellmanFord: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, edgeWeight: (edgeData: E) => number) => Option.Option<PathResult<E>>;
|
|
1193
|
+
/**
|
|
1194
|
+
* Concrete class for iterables that produce [NodeIndex, NodeData] tuples.
|
|
1195
|
+
*
|
|
1196
|
+
* This class provides a common abstraction for all iterables that return node data,
|
|
1197
|
+
* including traversal iterators (DFS, BFS, etc.) and element iterators (nodes, externals).
|
|
1198
|
+
* It uses a mapEntry function pattern for flexible iteration and transformation.
|
|
1199
|
+
*
|
|
1200
|
+
* @example
|
|
1201
|
+
* ```ts
|
|
1202
|
+
* import { Graph } from "effect"
|
|
1203
|
+
*
|
|
1204
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1205
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1206
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1207
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1208
|
+
* })
|
|
1209
|
+
*
|
|
1210
|
+
* // Both traversal and element iterators return NodeWalker
|
|
1211
|
+
* const dfsNodes: Graph.NodeWalker<string> = Graph.dfs(graph, { startNodes: [0] })
|
|
1212
|
+
* const allNodes: Graph.NodeWalker<string> = Graph.nodes(graph)
|
|
1213
|
+
*
|
|
1214
|
+
* // Common interface for working with node iterables
|
|
1215
|
+
* function processNodes<N>(nodeIterable: Graph.NodeWalker<N>): Array<number> {
|
|
1216
|
+
* return Array.from(Graph.indices(nodeIterable))
|
|
1217
|
+
* }
|
|
1218
|
+
*
|
|
1219
|
+
* // Access node data using values() or entries()
|
|
1220
|
+
* const nodeData = Array.from(Graph.values(dfsNodes)) // ["A", "B"]
|
|
1221
|
+
* const nodeEntries = Array.from(Graph.entries(allNodes)) // [[0, "A"], [1, "B"]]
|
|
1222
|
+
* ```
|
|
1223
|
+
*
|
|
1224
|
+
* @since 3.18.0
|
|
1225
|
+
* @category models
|
|
1226
|
+
*/
|
|
1227
|
+
export declare class Walker<T, N> implements Iterable<[T, N]> {
|
|
1228
|
+
readonly [Symbol.iterator]: () => Iterator<[T, N]>;
|
|
1229
|
+
/**
|
|
1230
|
+
* Visits each element and maps it to a value using the provided function.
|
|
1231
|
+
*
|
|
1232
|
+
* Takes a function that receives the index and data,
|
|
1233
|
+
* and returns an iterable of the mapped values. Skips elements that
|
|
1234
|
+
* no longer exist in the graph.
|
|
1235
|
+
*
|
|
1236
|
+
* @example
|
|
1237
|
+
* ```ts
|
|
1238
|
+
* import { Graph } from "effect"
|
|
1239
|
+
*
|
|
1240
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1241
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1242
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1243
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1244
|
+
* })
|
|
1245
|
+
*
|
|
1246
|
+
* const dfs = Graph.dfs(graph, { startNodes: [0] })
|
|
1247
|
+
*
|
|
1248
|
+
* // Map to just the node data
|
|
1249
|
+
* const values = Array.from(dfs.visit((index, data) => data))
|
|
1250
|
+
* console.log(values) // ["A", "B"]
|
|
1251
|
+
*
|
|
1252
|
+
* // Map to custom objects
|
|
1253
|
+
* const custom = Array.from(dfs.visit((index, data) => ({ id: index, name: data })))
|
|
1254
|
+
* console.log(custom) // [{ id: 0, name: "A" }, { id: 1, name: "B" }]
|
|
1255
|
+
* ```
|
|
1256
|
+
*
|
|
1257
|
+
* @since 3.18.0
|
|
1258
|
+
* @category iterators
|
|
1259
|
+
*/
|
|
1260
|
+
readonly visit: <U>(f: (index: T, data: N) => U) => Iterable<U>;
|
|
1261
|
+
constructor(
|
|
1262
|
+
/**
|
|
1263
|
+
* Visits each element and maps it to a value using the provided function.
|
|
1264
|
+
*
|
|
1265
|
+
* Takes a function that receives the index and data,
|
|
1266
|
+
* and returns an iterable of the mapped values. Skips elements that
|
|
1267
|
+
* no longer exist in the graph.
|
|
1268
|
+
*
|
|
1269
|
+
* @example
|
|
1270
|
+
* ```ts
|
|
1271
|
+
* import { Graph } from "effect"
|
|
1272
|
+
*
|
|
1273
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1274
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1275
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1276
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1277
|
+
* })
|
|
1278
|
+
*
|
|
1279
|
+
* const dfs = Graph.dfs(graph, { startNodes: [0] })
|
|
1280
|
+
*
|
|
1281
|
+
* // Map to just the node data
|
|
1282
|
+
* const values = Array.from(dfs.visit((index, data) => data))
|
|
1283
|
+
* console.log(values) // ["A", "B"]
|
|
1284
|
+
*
|
|
1285
|
+
* // Map to custom objects
|
|
1286
|
+
* const custom = Array.from(dfs.visit((index, data) => ({ id: index, name: data })))
|
|
1287
|
+
* console.log(custom) // [{ id: 0, name: "A" }, { id: 1, name: "B" }]
|
|
1288
|
+
* ```
|
|
1289
|
+
*
|
|
1290
|
+
* @since 3.18.0
|
|
1291
|
+
* @category iterators
|
|
1292
|
+
*/
|
|
1293
|
+
visit: <U>(f: (index: T, data: N) => U) => Iterable<U>);
|
|
1294
|
+
}
|
|
1295
|
+
/**
|
|
1296
|
+
* Type alias for node iteration using Walker.
|
|
1297
|
+
* NodeWalker is represented as Walker<NodeIndex, N>.
|
|
1298
|
+
*
|
|
1299
|
+
* @since 3.18.0
|
|
1300
|
+
* @category models
|
|
1301
|
+
*/
|
|
1302
|
+
export type NodeWalker<N> = Walker<NodeIndex, N>;
|
|
1303
|
+
/**
|
|
1304
|
+
* Type alias for edge iteration using Walker.
|
|
1305
|
+
* EdgeWalker is represented as Walker<EdgeIndex, Edge<E>>.
|
|
1306
|
+
*
|
|
1307
|
+
* @since 3.18.0
|
|
1308
|
+
* @category models
|
|
1309
|
+
*/
|
|
1310
|
+
export type EdgeWalker<E> = Walker<EdgeIndex, Edge<E>>;
|
|
1311
|
+
/**
|
|
1312
|
+
* Returns an iterator over the indices in the walker.
|
|
1313
|
+
*
|
|
1314
|
+
* @example
|
|
1315
|
+
* ```ts
|
|
1316
|
+
* import { Graph } from "effect"
|
|
1317
|
+
*
|
|
1318
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1319
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1320
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1321
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1322
|
+
* })
|
|
1323
|
+
*
|
|
1324
|
+
* const dfs = Graph.dfs(graph, { startNodes: [0] })
|
|
1325
|
+
* const indices = Array.from(Graph.indices(dfs))
|
|
1326
|
+
* console.log(indices) // [0, 1]
|
|
1327
|
+
* ```
|
|
1328
|
+
*
|
|
1329
|
+
* @since 3.18.0
|
|
1330
|
+
* @category utilities
|
|
1331
|
+
*/
|
|
1332
|
+
export declare const indices: <T, N>(walker: Walker<T, N>) => Iterable<T>;
|
|
1333
|
+
/**
|
|
1334
|
+
* Returns an iterator over the values (data) in the walker.
|
|
1335
|
+
*
|
|
1336
|
+
* @example
|
|
1337
|
+
* ```ts
|
|
1338
|
+
* import { Graph } from "effect"
|
|
1339
|
+
*
|
|
1340
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1341
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1342
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1343
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1344
|
+
* })
|
|
1345
|
+
*
|
|
1346
|
+
* const dfs = Graph.dfs(graph, { startNodes: [0] })
|
|
1347
|
+
* const values = Array.from(Graph.values(dfs))
|
|
1348
|
+
* console.log(values) // ["A", "B"]
|
|
1349
|
+
* ```
|
|
1350
|
+
*
|
|
1351
|
+
* @since 3.18.0
|
|
1352
|
+
* @category utilities
|
|
1353
|
+
*/
|
|
1354
|
+
export declare const values: <T, N>(walker: Walker<T, N>) => Iterable<N>;
|
|
1355
|
+
/**
|
|
1356
|
+
* Returns an iterator over [index, data] entries in the walker.
|
|
1357
|
+
*
|
|
1358
|
+
* @example
|
|
1359
|
+
* ```ts
|
|
1360
|
+
* import { Graph } from "effect"
|
|
1361
|
+
*
|
|
1362
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1363
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1364
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1365
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1366
|
+
* })
|
|
1367
|
+
*
|
|
1368
|
+
* const dfs = Graph.dfs(graph, { startNodes: [0] })
|
|
1369
|
+
* const entries = Array.from(Graph.entries(dfs))
|
|
1370
|
+
* console.log(entries) // [[0, "A"], [1, "B"]]
|
|
1371
|
+
* ```
|
|
1372
|
+
*
|
|
1373
|
+
* @since 3.18.0
|
|
1374
|
+
* @category utilities
|
|
1375
|
+
*/
|
|
1376
|
+
export declare const entries: <T, N>(walker: Walker<T, N>) => Iterable<[T, N]>;
|
|
1377
|
+
/**
|
|
1378
|
+
* Configuration options for DFS iterator.
|
|
1379
|
+
*
|
|
1380
|
+
* @since 3.18.0
|
|
1381
|
+
* @category models
|
|
1382
|
+
*/
|
|
1383
|
+
export interface DfsConfig {
|
|
1384
|
+
readonly startNodes?: Array<NodeIndex>;
|
|
1385
|
+
readonly direction?: Direction;
|
|
1386
|
+
}
|
|
1387
|
+
/**
|
|
1388
|
+
* Creates a new DFS iterator with optional configuration.
|
|
1389
|
+
*
|
|
1390
|
+
* The iterator maintains a stack of nodes to visit and tracks discovered nodes.
|
|
1391
|
+
* It provides lazy evaluation of the depth-first search.
|
|
1392
|
+
*
|
|
1393
|
+
* @example
|
|
1394
|
+
* ```ts
|
|
1395
|
+
* import { Graph } from "effect"
|
|
1396
|
+
*
|
|
1397
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1398
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1399
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1400
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1401
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1402
|
+
* Graph.addEdge(mutable, b, c, 1)
|
|
1403
|
+
* })
|
|
1404
|
+
*
|
|
1405
|
+
* // Start from a specific node
|
|
1406
|
+
* const dfs1 = Graph.dfs(graph, { startNodes: [0] })
|
|
1407
|
+
* for (const nodeIndex of Graph.indices(dfs1)) {
|
|
1408
|
+
* console.log(nodeIndex) // Traverses in DFS order: 0, 1, 2
|
|
1409
|
+
* }
|
|
1410
|
+
*
|
|
1411
|
+
* // Empty iterator (no starting nodes)
|
|
1412
|
+
* const dfs2 = Graph.dfs(graph)
|
|
1413
|
+
* // Can be used programmatically
|
|
1414
|
+
* ```
|
|
1415
|
+
*
|
|
1416
|
+
* @since 3.18.0
|
|
1417
|
+
* @category iterators
|
|
1418
|
+
*/
|
|
1419
|
+
export declare const dfs: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: DfsConfig) => NodeWalker<N>;
|
|
1420
|
+
/**
|
|
1421
|
+
* Configuration options for BFS iterator.
|
|
1422
|
+
*
|
|
1423
|
+
* @since 3.18.0
|
|
1424
|
+
* @category models
|
|
1425
|
+
*/
|
|
1426
|
+
export interface BfsConfig {
|
|
1427
|
+
readonly startNodes?: Array<NodeIndex>;
|
|
1428
|
+
readonly direction?: Direction;
|
|
1429
|
+
}
|
|
1430
|
+
/**
|
|
1431
|
+
* Creates a new BFS iterator with optional configuration.
|
|
1432
|
+
*
|
|
1433
|
+
* The iterator maintains a queue of nodes to visit and tracks discovered nodes.
|
|
1434
|
+
* It provides lazy evaluation of the breadth-first search.
|
|
1435
|
+
*
|
|
1436
|
+
* @example
|
|
1437
|
+
* ```ts
|
|
1438
|
+
* import { Graph } from "effect"
|
|
1439
|
+
*
|
|
1440
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1441
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1442
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1443
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1444
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1445
|
+
* Graph.addEdge(mutable, b, c, 1)
|
|
1446
|
+
* })
|
|
1447
|
+
*
|
|
1448
|
+
* // Start from a specific node
|
|
1449
|
+
* const bfs1 = Graph.bfs(graph, { startNodes: [0] })
|
|
1450
|
+
* for (const nodeIndex of Graph.indices(bfs1)) {
|
|
1451
|
+
* console.log(nodeIndex) // Traverses in BFS order: 0, 1, 2
|
|
1452
|
+
* }
|
|
1453
|
+
*
|
|
1454
|
+
* // Empty iterator (no starting nodes)
|
|
1455
|
+
* const bfs2 = Graph.bfs(graph)
|
|
1456
|
+
* // Can be used programmatically
|
|
1457
|
+
* ```
|
|
1458
|
+
*
|
|
1459
|
+
* @since 3.18.0
|
|
1460
|
+
* @category iterators
|
|
1461
|
+
*/
|
|
1462
|
+
export declare const bfs: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: BfsConfig) => NodeWalker<N>;
|
|
1463
|
+
/**
|
|
1464
|
+
* Configuration options for topological sort iterator.
|
|
1465
|
+
*
|
|
1466
|
+
* @since 3.18.0
|
|
1467
|
+
* @category models
|
|
1468
|
+
*/
|
|
1469
|
+
export interface TopoConfig {
|
|
1470
|
+
readonly initials?: Array<NodeIndex>;
|
|
1471
|
+
}
|
|
1472
|
+
/**
|
|
1473
|
+
* Creates a new topological sort iterator with optional configuration.
|
|
1474
|
+
*
|
|
1475
|
+
* The iterator uses Kahn's algorithm to lazily produce nodes in topological order.
|
|
1476
|
+
* Throws an error if the graph contains cycles.
|
|
1477
|
+
*
|
|
1478
|
+
* @example
|
|
1479
|
+
* ```ts
|
|
1480
|
+
* import { Graph } from "effect"
|
|
1481
|
+
*
|
|
1482
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1483
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1484
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1485
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1486
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1487
|
+
* Graph.addEdge(mutable, b, c, 1)
|
|
1488
|
+
* })
|
|
1489
|
+
*
|
|
1490
|
+
* // Standard topological sort
|
|
1491
|
+
* const topo1 = Graph.topo(graph)
|
|
1492
|
+
* for (const nodeIndex of Graph.indices(topo1)) {
|
|
1493
|
+
* console.log(nodeIndex) // 0, 1, 2 (topological order)
|
|
1494
|
+
* }
|
|
1495
|
+
*
|
|
1496
|
+
* // With initial nodes
|
|
1497
|
+
* const topo2 = Graph.topo(graph, { initials: [0] })
|
|
1498
|
+
*
|
|
1499
|
+
* // Throws error for cyclic graph
|
|
1500
|
+
* const cyclicGraph = Graph.directed<string, number>((mutable) => {
|
|
1501
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1502
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1503
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1504
|
+
* Graph.addEdge(mutable, b, a, 2) // Creates cycle
|
|
1505
|
+
* })
|
|
1506
|
+
*
|
|
1507
|
+
* try {
|
|
1508
|
+
* Graph.topo(cyclicGraph) // Throws: "Cannot perform topological sort on cyclic graph"
|
|
1509
|
+
* } catch (error) {
|
|
1510
|
+
* console.log((error as Error).message)
|
|
1511
|
+
* }
|
|
1512
|
+
* ```
|
|
1513
|
+
*
|
|
1514
|
+
* @since 3.18.0
|
|
1515
|
+
* @category iterators
|
|
1516
|
+
*/
|
|
1517
|
+
export declare const topo: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: TopoConfig) => NodeWalker<N>;
|
|
1518
|
+
/**
|
|
1519
|
+
* Configuration options for DFS postorder iterator.
|
|
1520
|
+
*
|
|
1521
|
+
* @since 3.18.0
|
|
1522
|
+
* @category models
|
|
1523
|
+
*/
|
|
1524
|
+
export interface DfsPostOrderConfig {
|
|
1525
|
+
readonly startNodes?: Array<NodeIndex>;
|
|
1526
|
+
readonly direction?: Direction;
|
|
1527
|
+
}
|
|
1528
|
+
/**
|
|
1529
|
+
* Creates a new DFS postorder iterator with optional configuration.
|
|
1530
|
+
*
|
|
1531
|
+
* The iterator maintains a stack with visit state tracking and emits nodes
|
|
1532
|
+
* in postorder (after all descendants have been processed). Essential for
|
|
1533
|
+
* dependency resolution and tree destruction algorithms.
|
|
1534
|
+
*
|
|
1535
|
+
* @example
|
|
1536
|
+
* ```ts
|
|
1537
|
+
* import { Graph } from "effect"
|
|
1538
|
+
*
|
|
1539
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1540
|
+
* const root = Graph.addNode(mutable, "root")
|
|
1541
|
+
* const child1 = Graph.addNode(mutable, "child1")
|
|
1542
|
+
* const child2 = Graph.addNode(mutable, "child2")
|
|
1543
|
+
* Graph.addEdge(mutable, root, child1, 1)
|
|
1544
|
+
* Graph.addEdge(mutable, root, child2, 1)
|
|
1545
|
+
* })
|
|
1546
|
+
*
|
|
1547
|
+
* // Postorder: children before parents
|
|
1548
|
+
* const postOrder = Graph.dfsPostOrder(graph, { startNodes: [0] })
|
|
1549
|
+
* for (const node of postOrder) {
|
|
1550
|
+
* console.log(node) // 1, 2, 0
|
|
1551
|
+
* }
|
|
1552
|
+
* ```
|
|
1553
|
+
*
|
|
1554
|
+
* @since 3.18.0
|
|
1555
|
+
* @category iterators
|
|
1556
|
+
*/
|
|
1557
|
+
export declare const dfsPostOrder: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: DfsPostOrderConfig) => NodeWalker<N>;
|
|
1558
|
+
/**
|
|
1559
|
+
* Creates an iterator over all node indices in the graph.
|
|
1560
|
+
*
|
|
1561
|
+
* The iterator produces node indices in the order they were added to the graph.
|
|
1562
|
+
* This provides access to all nodes regardless of connectivity.
|
|
1563
|
+
*
|
|
1564
|
+
* @example
|
|
1565
|
+
* ```ts
|
|
1566
|
+
* import { Graph } from "effect"
|
|
1567
|
+
*
|
|
1568
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1569
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1570
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1571
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1572
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1573
|
+
* })
|
|
1574
|
+
*
|
|
1575
|
+
* const indices = Array.from(Graph.indices(Graph.nodes(graph)))
|
|
1576
|
+
* console.log(indices) // [0, 1, 2]
|
|
1577
|
+
* ```
|
|
1578
|
+
*
|
|
1579
|
+
* @since 3.18.0
|
|
1580
|
+
* @category iterators
|
|
1581
|
+
*/
|
|
1582
|
+
export declare const nodes: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => NodeWalker<N>;
|
|
1583
|
+
/**
|
|
1584
|
+
* Creates an iterator over all edge indices in the graph.
|
|
1585
|
+
*
|
|
1586
|
+
* The iterator produces edge indices in the order they were added to the graph.
|
|
1587
|
+
* This provides access to all edges regardless of connectivity.
|
|
1588
|
+
*
|
|
1589
|
+
* @example
|
|
1590
|
+
* ```ts
|
|
1591
|
+
* import { Graph } from "effect"
|
|
1592
|
+
*
|
|
1593
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1594
|
+
* const a = Graph.addNode(mutable, "A")
|
|
1595
|
+
* const b = Graph.addNode(mutable, "B")
|
|
1596
|
+
* const c = Graph.addNode(mutable, "C")
|
|
1597
|
+
* Graph.addEdge(mutable, a, b, 1)
|
|
1598
|
+
* Graph.addEdge(mutable, b, c, 2)
|
|
1599
|
+
* })
|
|
1600
|
+
*
|
|
1601
|
+
* const indices = Array.from(Graph.indices(Graph.edges(graph)))
|
|
1602
|
+
* console.log(indices) // [0, 1]
|
|
1603
|
+
* ```
|
|
1604
|
+
*
|
|
1605
|
+
* @since 3.18.0
|
|
1606
|
+
* @category iterators
|
|
1607
|
+
*/
|
|
1608
|
+
export declare const edges: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => EdgeWalker<E>;
|
|
1609
|
+
/**
|
|
1610
|
+
* Configuration for externals iterator.
|
|
1611
|
+
*
|
|
1612
|
+
* @since 3.18.0
|
|
1613
|
+
* @category models
|
|
1614
|
+
*/
|
|
1615
|
+
export interface ExternalsConfig {
|
|
1616
|
+
readonly direction?: Direction;
|
|
1617
|
+
}
|
|
1618
|
+
/**
|
|
1619
|
+
* Creates an iterator over external nodes (nodes without edges in specified direction).
|
|
1620
|
+
*
|
|
1621
|
+
* External nodes are nodes that have no outgoing edges (direction="outgoing") or
|
|
1622
|
+
* no incoming edges (direction="incoming"). These are useful for finding
|
|
1623
|
+
* sources, sinks, or isolated nodes.
|
|
1624
|
+
*
|
|
1625
|
+
* @example
|
|
1626
|
+
* ```ts
|
|
1627
|
+
* import { Graph } from "effect"
|
|
1628
|
+
*
|
|
1629
|
+
* const graph = Graph.directed<string, number>((mutable) => {
|
|
1630
|
+
* const source = Graph.addNode(mutable, "source") // 0 - no incoming
|
|
1631
|
+
* const middle = Graph.addNode(mutable, "middle") // 1 - has both
|
|
1632
|
+
* const sink = Graph.addNode(mutable, "sink") // 2 - no outgoing
|
|
1633
|
+
* const isolated = Graph.addNode(mutable, "isolated") // 3 - no edges
|
|
1634
|
+
*
|
|
1635
|
+
* Graph.addEdge(mutable, source, middle, 1)
|
|
1636
|
+
* Graph.addEdge(mutable, middle, sink, 2)
|
|
1637
|
+
* })
|
|
1638
|
+
*
|
|
1639
|
+
* // Nodes with no outgoing edges (sinks + isolated)
|
|
1640
|
+
* const sinks = Array.from(Graph.indices(Graph.externals(graph, { direction: "outgoing" })))
|
|
1641
|
+
* console.log(sinks) // [2, 3]
|
|
1642
|
+
*
|
|
1643
|
+
* // Nodes with no incoming edges (sources + isolated)
|
|
1644
|
+
* const sources = Array.from(Graph.indices(Graph.externals(graph, { direction: "incoming" })))
|
|
1645
|
+
* console.log(sources) // [0, 3]
|
|
1646
|
+
* ```
|
|
1647
|
+
*
|
|
1648
|
+
* @since 3.18.0
|
|
1649
|
+
* @category iterators
|
|
1650
|
+
*/
|
|
1651
|
+
export declare const externals: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: ExternalsConfig) => NodeWalker<N>;
|
|
1652
|
+
//# sourceMappingURL=Graph.d.ts.map
|