/** * Models relationships between indexed nodes and edges. * * This module provides immutable and scoped-mutable graph data structures. A * graph can be directed or undirected, and it can store user-defined data on * both nodes and edges. The module includes traversal, analysis, path-finding, * transformation, and diagram export utilities. * * @stability unstable * @since 4.0.0 */ import * as Equal from "./Equal.ts"; import type { Inspectable } from "./Inspectable.ts"; import * as Option from "./Option.ts"; import type { Pipeable } from "./Pipeable.ts"; import type { Covariant, Invariant } from "./Types.ts"; declare const TypeId = "~effect/Graph"; /** * Node index for node identification using plain numbers. * * **When to use** * * Use when storing or passing the stable identifier of a graph node between * `Graph` operations. * * **Details** * * `addNode` allocates node identifiers from the graph's next node index. * * **Gotchas** * * A `NodeIndex` is an identifier, not an array offset. Removed node identifiers * are not reused. * * @see {@link EdgeIndex} for edge identifiers instead of node identifiers * * @stability unstable * @category models * @since 3.18.0 */ export type NodeIndex = number; /** * Edge index for edge identification using plain numbers. * * **When to use** * * Use when you need to keep the identifier for a graph edge so you can later * read, update, remove, or compare that edge. * * **Gotchas** * * An `EdgeIndex` is an identifier, not an array offset. Removed edge * identifiers are not reused. * * @see {@link NodeIndex} for node identifiers instead of edge identifiers * * @stability unstable * @category models * @since 3.18.0 */ export type EdgeIndex = number; /** * Represents edge data containing source, target, and user data. * * **When to use** * * Use as the graph edge value that carries source node, target node, and stored * edge data together. * * @stability unstable * @category models * @since 3.18.0 */ export interface Edge { readonly source: NodeIndex; readonly target: NodeIndex; readonly data: E; } /** * Graph type for distinguishing directed and undirected graphs. * * **When to use** * * Use when writing graph-polymorphic types or helpers that need to preserve * whether a graph is directed or undirected. * * @stability unstable * @category models * @since 3.18.0 */ export type Kind = "directed" | "undirected"; /** * A node and its stable index in a graph snapshot. * * @stability unstable * @category models * @since 4.0.0 */ export interface IndexedNode { readonly index: NodeIndex; readonly data: N; } /** * An edge and its stable index in a graph snapshot. * * @stability unstable * @category models * @since 4.0.0 */ export interface IndexedEdge extends Edge { readonly index: EdgeIndex; } /** * Active indexed structure used to reconstruct an immutable graph. * * **When to use** * * Use when serializing or importing graph structure while preserving active * node and edge identifiers. * * **Details** * * Node and edge indexes must be non-negative safe integers in strictly * increasing order. Every edge endpoint must reference an indexed node. * * **Gotchas** * * A snapshot records only active identifiers, not allocator history. After * reconstruction, new identifiers continue after the greatest active index. * * @see {@link fromSnapshot} for reconstructing a graph * @stability unstable * @category models * @since 4.0.0 */ export interface Snapshot { readonly type: T; readonly nodes: ReadonlyArray>; readonly edges: ReadonlyArray>; } /** * Immutable graph interface. * * **When to use** * * Use as the immutable graph model for code that queries, traverses, * transforms, or analyzes graph structure without mutating it. * * **Gotchas** * * After a graph is hashed, its transitively contained node and edge payloads * used by hashing must remain immutable, as with other Effect values. * * @see {@link MutableGraph} for the mutable counterpart used inside mutation scopes * * @stability unstable * @category models * @since 3.18.0 */ export interface Graph extends Iterable, Equal.Equal, Pipeable, Inspectable { readonly [TypeId]: Graph.Variance; readonly type: T; readonly mutable: false; } /** * Companion namespace containing type-level metadata for immutable graphs. * * @stability unstable * @category models * @since 4.0.0 */ export declare namespace Graph { /** * Type-level variance marker for immutable graphs. * * @category utility types * @since 4.0.0 */ interface Variance { readonly _N: Covariant; readonly _E: Covariant; } } /** * Mutable graph interface. * * **When to use** * * Use when adding, removing, or updating nodes and edges inside a graph * mutation scope. * * **Gotchas** * * A callback invoked by another graph operation may query the same mutable * graph, but cannot mutate or finalize it. Mutation is allowed in callbacks * passed to graph constructors and `mutate`, where mutation is the purpose. * * @see {@link Graph} for the immutable graph interface * @see {@link mutate} for scoped mutation of an immutable graph * * @stability unstable * @category models * @since 3.18.0 */ export interface MutableGraph extends Iterable, Equal.Equal, Pipeable, Inspectable { readonly [TypeId]: MutableGraph.Variance; readonly type: T; readonly mutable: true; } /** * Companion namespace containing type-level metadata for scoped mutable graphs. * * @stability unstable * @category models * @since 4.0.0 */ export declare namespace MutableGraph { /** * Type-level variance marker for scoped mutable graphs. * * @category utility types * @since 4.0.0 */ interface Variance { readonly _N: Invariant; readonly _E: Invariant; } } /** * Immutable graph type for source-to-target relationships. * * **When to use** * * Use as the immutable graph type when edge direction is part of the model and * traversal or neighbor queries should follow source-to-target edges. * * **Details** * * `DirectedGraph` is a `Graph` with node data of type * `N` and edge data of type `E`. * * @see {@link directed} for constructing directed graphs * @see {@link UndirectedGraph} for graphs whose edges connect both endpoints * * @stability unstable * @category models * @since 3.18.0 */ export type DirectedGraph = Graph; /** * Immutable graph type for relationships without source-to-target direction. * * **When to use** * * Use when modeling relationships where each edge connects both endpoints * without a source-to-target direction. * * **Details** * * `UndirectedGraph` is a `Graph`. * * @see {@link undirected} for constructing undirected graphs * @see {@link DirectedGraph} for graphs whose edges have source-to-target direction * * @stability unstable * @category models * @since 3.18.0 */ export type UndirectedGraph = Graph; /** * Mutable directed graph type alias. * * **When to use** * * Use when annotating a temporary graph value that can be changed in place and * whose edges have source-to-target direction. * * @see {@link MutableGraph} for the generic mutable graph type * @see {@link MutableUndirectedGraph} for mutable graphs without edge direction * * @stability unstable * @category models * @since 3.18.0 */ export type MutableDirectedGraph = MutableGraph; /** * Mutable undirected graph type alias. * * **When to use** * * Use when annotating a temporary graph value that can be changed in place and * whose edges connect both endpoints without direction. * * @see {@link MutableDirectedGraph} for mutable graphs with directed edges * @see {@link MutableGraph} for the generic mutable graph type * * @stability unstable * @category models * @since 3.18.0 */ export type MutableUndirectedGraph = MutableGraph; declare const GraphError_base: new = {}>(args: import("./Types.ts").VoidIfEmpty<{ readonly [P in keyof A as P extends "_tag" ? never : P]: A[P]; }>) => import("./Cause.ts").YieldableError & { readonly _tag: "GraphError"; } & Readonly; /** * Error thrown by graph operations when the requested graph structure is * invalid, such as referencing a missing node or using unsupported edge * weights. * * **When to use** * * Use when handling failures thrown by graph operations that reject invalid * graph structure or unsupported algorithm inputs. * * @stability unstable * @category errors * @since 3.18.0 */ export declare class GraphError extends GraphError_base<{ readonly message: string; }> { } /** * Returns `true` if a value has the graph runtime type identifier, narrowing * it to an immutable or mutable graph. * * **When to use** * * Use to narrow an unknown value before treating it as a graph value. * * **Gotchas** * * This guard checks the shared graph runtime type identifier and does not * distinguish immutable graphs from mutable graphs or directed graphs from * undirected graphs. * * @stability unstable * @category guards * @since 4.0.0 */ export declare const isGraph: (u: U | Graph | MutableGraph) => u is Graph | MutableGraph; /** * Reconstructs an immutable graph from its indexed active structure. * * **When to use** * * Use when importing a snapshot or other externally indexed graph structure. * Prefer `directed` or `undirected` when creating a new graph without existing * identifiers. * * **Gotchas** * * The node and edge arrays must be ordered by strictly increasing, * non-negative safe integer indexes, and every edge endpoint must reference a * node in the snapshot. Invalid snapshots throw a `GraphError`. Historical * removed identifiers after the greatest active index are not retained. * * **Example** (Preserving graph indexes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.fromSnapshot({ * type: "directed", * nodes: [{ index: 2, data: "A" }, { index: 5, data: "B" }], * edges: [{ index: 3, source: 2, target: 5, data: 1 }] * }) * * Graph.toSnapshot(graph).edges[0].index // => 3 * ``` * * @see {@link toSnapshot} for capturing a graph snapshot * @stability unstable * @category constructors * @since 4.0.0 */ export declare const fromSnapshot: (snapshot: Snapshot) => Graph; /** * Returns the active indexed structure of a graph. * * **When to use** * * Use when serializing a graph or passing its active structure across a * boundary where node and edge identifiers must be preserved. * * **Details** * * Nodes and edges are returned in graph order with their current indexes. * Undirected edges retain their stored endpoint orientation, and each returned * node and edge record is newly allocated. The operation runs in `O(V + E)`. * * **Gotchas** * * Node and edge payloads are not cloned. The snapshot also omits allocator * history for identifiers that are no longer active. * * **Example** (Round-tripping a graph snapshot) * * ```ts import.meta.vitest * import { Equal, Graph } from "effect" * * const graph = Graph.fromSnapshot({ * type: "undirected", * nodes: [{ index: 2, data: "A" }, { index: 5, data: "B" }], * edges: [{ index: 3, source: 5, target: 2, data: "A-B" }] * }) * * Equal.equals(Graph.fromSnapshot(Graph.toSnapshot(graph)), graph) // => true * ``` * * @see {@link fromSnapshot} for reconstructing an immutable graph * @stability unstable * @category converting * @since 4.0.0 */ export declare const toSnapshot: (graph: Graph | MutableGraph) => Snapshot; /** * Creates a graph constructor for the specified graph kind. * * **When to use** * * Use when the graph kind is selected dynamically. Prefer `directed` or * `undirected` when the kind is known statically. * * **Example** (Constructing by kind) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const makeGraph = Graph.make("directed") * const graph = makeGraph((mutable) => { * Graph.addNode(mutable, "A") * }) * * graph.type // => "directed" * ``` * * @see {@link directed} for constructing a directed graph directly * @see {@link undirected} for constructing an undirected graph directly * @stability unstable * @category constructors * @since 4.0.0 */ export declare const make: (type: T) => (mutate?: (mutable: MutableGraph) => undefined) => Graph; /** * Creates a directed graph, optionally with initial mutations. * * **When to use** * * Use when relationships have a source-to-target direction, such as * dependencies, workflows, or routing links. * * **Gotchas** * * The mutable callback handle is finalized when the callback returns and must * not be retained for later mutation. * * **Example** (Creating a directed graph) * * ```ts import.meta.vitest * import { Graph } from "effect" * * // Directed graph with initial nodes and edges * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A->B") * Graph.addEdge(mutable, b, c, "B->C") * }) * Array.of(Graph.nodeCount(graph), Graph.edgeCount(graph)) // => [3, 2] * ``` * * @stability unstable * @category constructors * @since 3.18.0 */ export declare const directed: (mutate?: (mutable: MutableDirectedGraph) => undefined) => DirectedGraph; /** * Creates an undirected graph, optionally with initial mutations. * * **When to use** * * Use when relationships connect both endpoints symmetrically, such as social * connections or physical links. * * **Gotchas** * * The mutable callback handle is finalized when the callback returns and must * not be retained for later mutation. * * **Example** (Creating an undirected graph) * * ```ts import.meta.vitest * import { Graph } from "effect" * * // Undirected graph with initial nodes and edges * const graph = Graph.undirected((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * Array.of(Graph.nodeCount(graph), Graph.edgeCount(graph)) // => [3, 2] * ``` * * @stability unstable * @category constructors * @since 3.18.0 */ export declare const undirected: (mutate?: (mutable: MutableUndirectedGraph) => undefined) => UndirectedGraph; /** * Creates a mutable copy of an immutable graph for a manual mutation scope. * * **When to use** * * Use when a mutation scope must span code that cannot be expressed as one * `mutate` callback. * * **Gotchas** * * The graph structure is copied, but node and edge payload objects remain * shared by reference. Always finish the scope with `endMutation`; prefer * `mutate` when a callback is sufficient. * * **Example** (Beginning a mutation scope) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed() * const mutable = Graph.beginMutation(graph) * // Now mutable can be safely modified without affecting original graph * Array.of(Graph.nodeCount(mutable), Graph.nodeCount(graph)) // => [0, 0] * ``` * * @see {@link endMutation} for finalizing the mutable graph * @see {@link mutate} for automatically scoped mutation * @stability unstable * @category mutations * @since 3.18.0 */ export declare const beginMutation: (graph: Graph) => MutableGraph; /** * Converts a mutable graph back to an immutable graph, ending the mutation scope. * * **When to use** * * Use to finish a mutation scope opened with `beginMutation`. * * **Gotchas** * * Finalization is terminal. Later public mutation operations on the same * mutable handle fail with a `GraphError`. * * **Example** (Ending a mutation scope) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed() * const mutable = Graph.beginMutation(graph) * // ... perform mutations on mutable ... * Graph.nodeCount(Graph.endMutation(mutable)) // => 0 * ``` * * @see {@link beginMutation} for opening a manual mutation scope * @see {@link mutate} for automatically scoped mutation * @stability unstable * @category mutations * @since 3.18.0 */ export declare const endMutation: (mutable: MutableGraph) => Graph; /** * Returns an immutable graph after applying scoped mutations to a structural copy. * * **When to use** * * Use when several node or edge * mutations should be applied together. * * **Details** * * The original graph remains structurally unchanged. The mutable callback * handle is finalized whether the callback returns or throws. * * **Gotchas** * * Payload objects are shared unless the callback replaces them. A callback * failure is rethrown after the mutable handle is finalized, and the handle * must not escape for later mutation. * * **Example** (Applying scoped mutations) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed() * const newGraph = Graph.mutate(graph, (mutable) => { * const nodeA = Graph.addNode(mutable, "A") * const nodeB = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, nodeA, nodeB, 1) * }) * * Graph.nodeCount(newGraph) // => 2 * Graph.edgeCount(newGraph) // => 1 * ``` * * @see {@link beginMutation} for opening a manual mutation scope * @see {@link endMutation} for finalizing a manual mutation scope * @stability unstable * @category mutations * @since 3.18.0 */ export declare const mutate: { /** * Returns an immutable graph after applying scoped mutations to a structural copy. * * **When to use** * * Use when several node or edge * mutations should be applied together. * * **Details** * * The original graph remains structurally unchanged. The mutable callback * handle is finalized whether the callback returns or throws. * * **Gotchas** * * Payload objects are shared unless the callback replaces them. A callback * failure is rethrown after the mutable handle is finalized, and the handle * must not escape for later mutation. * * **Example** (Applying scoped mutations) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed() * const newGraph = Graph.mutate(graph, (mutable) => { * const nodeA = Graph.addNode(mutable, "A") * const nodeB = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, nodeA, nodeB, 1) * }) * * Graph.nodeCount(newGraph) // => 2 * Graph.edgeCount(newGraph) // => 1 * ``` * * @see {@link beginMutation} for opening a manual mutation scope * @see {@link endMutation} for finalizing a manual mutation scope * @stability unstable * @category mutations * @since 3.18.0 */ (f: (mutable: MutableGraph) => undefined): (graph: Graph) => Graph; /** * Returns an immutable graph after applying scoped mutations to a structural copy. * * **When to use** * * Use when several node or edge * mutations should be applied together. * * **Details** * * The original graph remains structurally unchanged. The mutable callback * handle is finalized whether the callback returns or throws. * * **Gotchas** * * Payload objects are shared unless the callback replaces them. A callback * failure is rethrown after the mutable handle is finalized, and the handle * must not escape for later mutation. * * **Example** (Applying scoped mutations) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed() * const newGraph = Graph.mutate(graph, (mutable) => { * const nodeA = Graph.addNode(mutable, "A") * const nodeB = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, nodeA, nodeB, 1) * }) * * Graph.nodeCount(newGraph) // => 2 * Graph.edgeCount(newGraph) // => 1 * ``` * * @see {@link beginMutation} for opening a manual mutation scope * @see {@link endMutation} for finalizing a manual mutation scope * @stability unstable * @category mutations * @since 3.18.0 */ (graph: Graph, f: (mutable: MutableGraph) => undefined): Graph; }; /** * Configures node and edge identity for graph set operations. * * **When to use** * * Use when logical graph membership should be based on a stable key rather * than the complete node or edge payload. * * **Details** * * Both functions default to using the complete node or edge data. Edge identity * also includes the identities of its endpoint nodes and the graph kind. * Projected identities use Effect equality and hashing semantics. * * **Gotchas** * * Edge identity defines set membership, not edge multiplicity. Parallel edges * with the same endpoint identities and projected edge identity are treated as * the same member by graph set operations. * * @stability unstable * @category configuration * @since 4.0.0 */ export interface IdentityOptions { readonly nodeIdentity?: (node: N) => NI; readonly edgeIdentity?: (edge: E) => EI; } /** * Composes two graphs, merging nodes by identity. * * **When to use** * * Use when combining graphs that describe overlapping logical entities and * should merge those entities by payload or a projected identity. * * **Details** * * Nodes and edges present in both graphs use data from `that`. The result has * the same graph kind as `self`. Throws a `GraphError` when the graph kinds do * not match. `nodeIdentity` and `edgeIdentity` default to the complete node and * edge data. Edge identity also includes the endpoint identities. * * `G1 ∪ G2 = {V1 ∪ V2, E1 ∪ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * Parallel edges with equal identities are also coalesced, with the last edge * supplying the data. The result allocates new node and edge identifiers. * * **Example** (Combining graphs) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed<{ id: string }, string>((mutable) => { * const a = Graph.addNode(mutable, { id: "A" }) * const b = Graph.addNode(mutable, { id: "B" }) * Graph.addEdge(mutable, a, b, "A-B") * }) * * const right = Graph.directed<{ id: string }, string>((mutable) => { * const b = Graph.addNode(mutable, { id: "B" }) * const c = Graph.addNode(mutable, { id: "C" }) * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.compose(left, right, { * nodeIdentity: (node) => node.id * }) * * Graph.nodeCount(result) // => 3 * Graph.edgeCount(result) // => 2 * ``` * * @see {@link sum} for combining graphs without merging equal nodes * @stability unstable * @category set operations * @since 4.0.0 */ export declare const compose: { /** * Composes two graphs, merging nodes by identity. * * **When to use** * * Use when combining graphs that describe overlapping logical entities and * should merge those entities by payload or a projected identity. * * **Details** * * Nodes and edges present in both graphs use data from `that`. The result has * the same graph kind as `self`. Throws a `GraphError` when the graph kinds do * not match. `nodeIdentity` and `edgeIdentity` default to the complete node and * edge data. Edge identity also includes the endpoint identities. * * `G1 ∪ G2 = {V1 ∪ V2, E1 ∪ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * Parallel edges with equal identities are also coalesced, with the last edge * supplying the data. The result allocates new node and edge identifiers. * * **Example** (Combining graphs) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed<{ id: string }, string>((mutable) => { * const a = Graph.addNode(mutable, { id: "A" }) * const b = Graph.addNode(mutable, { id: "B" }) * Graph.addEdge(mutable, a, b, "A-B") * }) * * const right = Graph.directed<{ id: string }, string>((mutable) => { * const b = Graph.addNode(mutable, { id: "B" }) * const c = Graph.addNode(mutable, { id: "C" }) * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.compose(left, right, { * nodeIdentity: (node) => node.id * }) * * Graph.nodeCount(result) // => 3 * Graph.edgeCount(result) // => 2 * ``` * * @see {@link sum} for combining graphs without merging equal nodes * @stability unstable * @category set operations * @since 4.0.0 */ (that: Graph, options?: IdentityOptions): (self: Graph>) => Graph; /** * Composes two graphs, merging nodes by identity. * * **When to use** * * Use when combining graphs that describe overlapping logical entities and * should merge those entities by payload or a projected identity. * * **Details** * * Nodes and edges present in both graphs use data from `that`. The result has * the same graph kind as `self`. Throws a `GraphError` when the graph kinds do * not match. `nodeIdentity` and `edgeIdentity` default to the complete node and * edge data. Edge identity also includes the endpoint identities. * * `G1 ∪ G2 = {V1 ∪ V2, E1 ∪ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * Parallel edges with equal identities are also coalesced, with the last edge * supplying the data. The result allocates new node and edge identifiers. * * **Example** (Combining graphs) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed<{ id: string }, string>((mutable) => { * const a = Graph.addNode(mutable, { id: "A" }) * const b = Graph.addNode(mutable, { id: "B" }) * Graph.addEdge(mutable, a, b, "A-B") * }) * * const right = Graph.directed<{ id: string }, string>((mutable) => { * const b = Graph.addNode(mutable, { id: "B" }) * const c = Graph.addNode(mutable, { id: "C" }) * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.compose(left, right, { * nodeIdentity: (node) => node.id * }) * * Graph.nodeCount(result) // => 3 * Graph.edgeCount(result) // => 2 * ``` * * @see {@link sum} for combining graphs without merging equal nodes * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, that: Graph>, options?: IdentityOptions): Graph; }; /** * Returns the intersection of two graphs, matching nodes by identity. * * **When to use** * * Use when extracting nodes and edges that represent the same logical * structure in both graphs. * * **Details** * * Node data comes from `self`, and edge data comes from `that`. The result has * the same graph kind as `self`. Throws a `GraphError` when the graph kinds do * not match. `nodeIdentity` and `edgeIdentity` default to the complete node and * edge data. Edge identity also includes the endpoint identities. * * `G1 ∩ G2 = {V1 ∩ V2, E1 ∩ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * The result contains at most one edge for each shared edge identity and * allocates new node and edge identifiers. * * **Example** (Finding shared structure) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "shared") * }) * * const right = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "shared") * }) * * const result = Graph.intersection(left, right) * * Graph.nodeCount(result) // => 2 * Graph.edgeCount(result) // => 1 * ``` * * @see {@link compose} for identity-based graph union * @stability unstable * @category set operations * @since 4.0.0 */ export declare const intersection: { /** * Returns the intersection of two graphs, matching nodes by identity. * * **When to use** * * Use when extracting nodes and edges that represent the same logical * structure in both graphs. * * **Details** * * Node data comes from `self`, and edge data comes from `that`. The result has * the same graph kind as `self`. Throws a `GraphError` when the graph kinds do * not match. `nodeIdentity` and `edgeIdentity` default to the complete node and * edge data. Edge identity also includes the endpoint identities. * * `G1 ∩ G2 = {V1 ∩ V2, E1 ∩ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * The result contains at most one edge for each shared edge identity and * allocates new node and edge identifiers. * * **Example** (Finding shared structure) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "shared") * }) * * const right = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "shared") * }) * * const result = Graph.intersection(left, right) * * Graph.nodeCount(result) // => 2 * Graph.edgeCount(result) // => 1 * ``` * * @see {@link compose} for identity-based graph union * @stability unstable * @category set operations * @since 4.0.0 */ (that: Graph, options?: IdentityOptions): (self: Graph>) => Graph; /** * Returns the intersection of two graphs, matching nodes by identity. * * **When to use** * * Use when extracting nodes and edges that represent the same logical * structure in both graphs. * * **Details** * * Node data comes from `self`, and edge data comes from `that`. The result has * the same graph kind as `self`. Throws a `GraphError` when the graph kinds do * not match. `nodeIdentity` and `edgeIdentity` default to the complete node and * edge data. Edge identity also includes the endpoint identities. * * `G1 ∩ G2 = {V1 ∩ V2, E1 ∩ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * The result contains at most one edge for each shared edge identity and * allocates new node and edge identifiers. * * **Example** (Finding shared structure) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "shared") * }) * * const right = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "shared") * }) * * const result = Graph.intersection(left, right) * * Graph.nodeCount(result) // => 2 * Graph.edgeCount(result) // => 1 * ``` * * @see {@link compose} for identity-based graph union * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, that: Graph>, options?: IdentityOptions): Graph; }; /** * Returns `self` without edges also present in `that`. * * **When to use** * * Use when retaining all logical nodes from one graph while removing edge * relationships also represented by another graph. * * **Details** * * All nodes from `self` are preserved. Edges are matched by endpoint and edge * identities. The result has the same graph kind as `self`. Throws a * `GraphError` when the graph kinds do not match. `nodeIdentity` and * `edgeIdentity` default to the complete node and edge data. * * `G1 \ G2 = {V1, E1 \ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * If `that` contains an edge identity, every parallel edge with that identity * is removed from `self`. The result allocates new node and edge identifiers. * * **Example** (Removing shared edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const right = Graph.directed((mutable) => { * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.difference(left, right) * * Graph.nodeCount(result) // => 3 * Graph.edgeCount(result) // => 1 * ``` * * @see {@link symmetricDifference} for retaining edges unique to either graph * @stability unstable * @category set operations * @since 4.0.0 */ export declare const difference: { /** * Returns `self` without edges also present in `that`. * * **When to use** * * Use when retaining all logical nodes from one graph while removing edge * relationships also represented by another graph. * * **Details** * * All nodes from `self` are preserved. Edges are matched by endpoint and edge * identities. The result has the same graph kind as `self`. Throws a * `GraphError` when the graph kinds do not match. `nodeIdentity` and * `edgeIdentity` default to the complete node and edge data. * * `G1 \ G2 = {V1, E1 \ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * If `that` contains an edge identity, every parallel edge with that identity * is removed from `self`. The result allocates new node and edge identifiers. * * **Example** (Removing shared edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const right = Graph.directed((mutable) => { * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.difference(left, right) * * Graph.nodeCount(result) // => 3 * Graph.edgeCount(result) // => 1 * ``` * * @see {@link symmetricDifference} for retaining edges unique to either graph * @stability unstable * @category set operations * @since 4.0.0 */ (that: Graph, options?: IdentityOptions): (self: Graph>) => Graph; /** * Returns `self` without edges also present in `that`. * * **When to use** * * Use when retaining all logical nodes from one graph while removing edge * relationships also represented by another graph. * * **Details** * * All nodes from `self` are preserved. Edges are matched by endpoint and edge * identities. The result has the same graph kind as `self`. Throws a * `GraphError` when the graph kinds do not match. `nodeIdentity` and * `edgeIdentity` default to the complete node and edge data. * * `G1 \ G2 = {V1, E1 \ E2}` * * **Gotchas** * * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * If `that` contains an edge identity, every parallel edge with that identity * is removed from `self`. The result allocates new node and edge identifiers. * * **Example** (Removing shared edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const right = Graph.directed((mutable) => { * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.difference(left, right) * * Graph.nodeCount(result) // => 3 * Graph.edgeCount(result) // => 1 * ``` * * @see {@link symmetricDifference} for retaining edges unique to either graph * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, that: Graph>, options?: IdentityOptions): Graph; }; /** * Returns edges present in exactly one of two graphs. * * **When to use** * * Use when comparing graphs and retaining relationships unique to either one. * * **Details** * * Keeps nodes from both graphs. Overlapping nodes use data from `that`. The * result has the same graph kind as `self`. Throws a `GraphError` when the * graph kinds do not match. `nodeIdentity` and `edgeIdentity` default to the * complete node and edge data. Edge identity also includes the endpoint * identities. * * `G1 Δ G2 = {V1 ∪ V2, (E1 ∪ E2) \ (E1 ∩ E2)}` * * **Gotchas** * * Edges with different projected identities are distinct. * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * Parallel edges with equal identities are coalesced before the graphs are * compared. The result allocates new node and edge identifiers. * * **Example** (Finding differing edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const right = Graph.directed((mutable) => { * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * const d = Graph.addNode(mutable, "D") * Graph.addEdge(mutable, b, c, "B-C") * Graph.addEdge(mutable, c, d, "C-D") * }) * * const result = Graph.symmetricDifference(left, right) * * Graph.nodeCount(result) // => 4 * Graph.edgeCount(result) // => 2 * ``` * * @see {@link difference} for removing only the edges found in another graph * @stability unstable * @category set operations * @since 4.0.0 */ export declare const symmetricDifference: { /** * Returns edges present in exactly one of two graphs. * * **When to use** * * Use when comparing graphs and retaining relationships unique to either one. * * **Details** * * Keeps nodes from both graphs. Overlapping nodes use data from `that`. The * result has the same graph kind as `self`. Throws a `GraphError` when the * graph kinds do not match. `nodeIdentity` and `edgeIdentity` default to the * complete node and edge data. Edge identity also includes the endpoint * identities. * * `G1 Δ G2 = {V1 ∪ V2, (E1 ∪ E2) \ (E1 ∩ E2)}` * * **Gotchas** * * Edges with different projected identities are distinct. * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * Parallel edges with equal identities are coalesced before the graphs are * compared. The result allocates new node and edge identifiers. * * **Example** (Finding differing edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const right = Graph.directed((mutable) => { * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * const d = Graph.addNode(mutable, "D") * Graph.addEdge(mutable, b, c, "B-C") * Graph.addEdge(mutable, c, d, "C-D") * }) * * const result = Graph.symmetricDifference(left, right) * * Graph.nodeCount(result) // => 4 * Graph.edgeCount(result) // => 2 * ``` * * @see {@link difference} for removing only the edges found in another graph * @stability unstable * @category set operations * @since 4.0.0 */ (that: Graph, options?: IdentityOptions): (self: Graph>) => Graph; /** * Returns edges present in exactly one of two graphs. * * **When to use** * * Use when comparing graphs and retaining relationships unique to either one. * * **Details** * * Keeps nodes from both graphs. Overlapping nodes use data from `that`. The * result has the same graph kind as `self`. Throws a `GraphError` when the * graph kinds do not match. `nodeIdentity` and `edgeIdentity` default to the * complete node and edge data. Edge identity also includes the endpoint * identities. * * `G1 Δ G2 = {V1 ∪ V2, (E1 ∪ E2) \ (E1 ∩ E2)}` * * **Gotchas** * * Edges with different projected identities are distinct. * Nodes with equal identities in one input graph are coalesced. The last node * supplies the data, and redirected edges can collapse or become self-loops. * Parallel edges with equal identities are coalesced before the graphs are * compared. The result allocates new node and edge identifiers. * * **Example** (Finding differing edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const left = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const right = Graph.directed((mutable) => { * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * const d = Graph.addNode(mutable, "D") * Graph.addEdge(mutable, b, c, "B-C") * Graph.addEdge(mutable, c, d, "C-D") * }) * * const result = Graph.symmetricDifference(left, right) * * Graph.nodeCount(result) // => 4 * Graph.edgeCount(result) // => 2 * ``` * * @see {@link difference} for removing only the edges found in another graph * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, that: Graph>, options?: IdentityOptions): Graph; }; /** * Returns the complement over the existing node set. * * **When to use** * * Use when materializing every relationship that is currently absent between * distinct nodes. * * **Details** * * Directed graphs add each missing ordered pair. Undirected graphs add each * missing unordered pair once. The `createEdge` function receives the source * and target node data for each added edge. The result has the same graph kind * as `self`. * * `G' = {V, ((V x V) without self-pairs) \ E}` * * **Gotchas** * * Self-loops are never created. If any edge already connects a pair, parallel * complement edges are not added. The result allocates new identifiers. * * **Example** (Finding missing relationships) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "A-B") * }) * * const result = Graph.complement(graph, (source, target) => `${source}-${target}`) * * Graph.edgeCount(result) // => 1 * ``` * * @see {@link hasEdge} for testing one relationship * @stability unstable * @category set operations * @since 4.0.0 */ export declare const complement: { /** * Returns the complement over the existing node set. * * **When to use** * * Use when materializing every relationship that is currently absent between * distinct nodes. * * **Details** * * Directed graphs add each missing ordered pair. Undirected graphs add each * missing unordered pair once. The `createEdge` function receives the source * and target node data for each added edge. The result has the same graph kind * as `self`. * * `G' = {V, ((V x V) without self-pairs) \ E}` * * **Gotchas** * * Self-loops are never created. If any edge already connects a pair, parallel * complement edges are not added. The result allocates new identifiers. * * **Example** (Finding missing relationships) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "A-B") * }) * * const result = Graph.complement(graph, (source, target) => `${source}-${target}`) * * Graph.edgeCount(result) // => 1 * ``` * * @see {@link hasEdge} for testing one relationship * @stability unstable * @category set operations * @since 4.0.0 */ (createEdge: (source: N, target: N) => E): (self: Graph) => Graph; /** * Returns the complement over the existing node set. * * **When to use** * * Use when materializing every relationship that is currently absent between * distinct nodes. * * **Details** * * Directed graphs add each missing ordered pair. Undirected graphs add each * missing unordered pair once. The `createEdge` function receives the source * and target node data for each added edge. The result has the same graph kind * as `self`. * * `G' = {V, ((V x V) without self-pairs) \ E}` * * **Gotchas** * * Self-loops are never created. If any edge already connects a pair, parallel * complement edges are not added. The result allocates new identifiers. * * **Example** (Finding missing relationships) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "A-B") * }) * * const result = Graph.complement(graph, (source, target) => `${source}-${target}`) * * Graph.edgeCount(result) // => 1 * ``` * * @see {@link hasEdge} for testing one relationship * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, createEdge: (source: N, target: N) => E): Graph; }; /** * Configuration for selecting a graph neighborhood. * * **Details** * * `radius` limits the edge distance from the center node and defaults to `1`. * It accepts non-negative integers and `Infinity`. * `direction` controls how directed edges are traversed and defaults to * `"outgoing"`. * * @stability unstable * @category configuration * @since 4.0.0 */ export interface NeighborhoodConfig { readonly radius?: number; readonly direction?: TraversalDirection; } /** * Returns the induced subgraph containing nodes within a radius of a node. * * **When to use** * * Use when extracting a local reachable region around one node. * * **Details** * * The `radius` option is the maximum edge distance from `nodeIndex`, accepts * non-negative integers and `Infinity`, and defaults to `1`. Invalid radii * throw a `GraphError`. The `direction` option controls directed graph * traversal and defaults to `"outgoing"`. The result has the same graph kind * as `self` and keeps all original edges whose endpoints are both reached. * `"undirected"` ignores edge direction while finding reachable nodes. * * **Gotchas** * * Traversal chooses the nodes, then all original edges between reached nodes * are retained. The result is not merely a traversal tree, and it allocates new * node and edge identifiers. * * **Example** (Getting a local neighborhood) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.neighborhood(graph, 1, { radius: 1 }) * * Graph.nodeCount(result) // => 2 * ``` * * @see {@link inducedSubgraph} for selecting nodes while preserving identifiers * @stability unstable * @category set operations * @since 4.0.0 */ export declare const neighborhood: { /** * Returns the induced subgraph containing nodes within a radius of a node. * * **When to use** * * Use when extracting a local reachable region around one node. * * **Details** * * The `radius` option is the maximum edge distance from `nodeIndex`, accepts * non-negative integers and `Infinity`, and defaults to `1`. Invalid radii * throw a `GraphError`. The `direction` option controls directed graph * traversal and defaults to `"outgoing"`. The result has the same graph kind * as `self` and keeps all original edges whose endpoints are both reached. * `"undirected"` ignores edge direction while finding reachable nodes. * * **Gotchas** * * Traversal chooses the nodes, then all original edges between reached nodes * are retained. The result is not merely a traversal tree, and it allocates new * node and edge identifiers. * * **Example** (Getting a local neighborhood) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.neighborhood(graph, 1, { radius: 1 }) * * Graph.nodeCount(result) // => 2 * ``` * * @see {@link inducedSubgraph} for selecting nodes while preserving identifiers * @stability unstable * @category set operations * @since 4.0.0 */ (nodeIndex: NodeIndex, options?: NeighborhoodConfig): (self: Graph) => Graph; /** * Returns the induced subgraph containing nodes within a radius of a node. * * **When to use** * * Use when extracting a local reachable region around one node. * * **Details** * * The `radius` option is the maximum edge distance from `nodeIndex`, accepts * non-negative integers and `Infinity`, and defaults to `1`. Invalid radii * throw a `GraphError`. The `direction` option controls directed graph * traversal and defaults to `"outgoing"`. The result has the same graph kind * as `self` and keeps all original edges whose endpoints are both reached. * `"undirected"` ignores edge direction while finding reachable nodes. * * **Gotchas** * * Traversal chooses the nodes, then all original edges between reached nodes * are retained. The result is not merely a traversal tree, and it allocates new * node and edge identifiers. * * **Example** (Getting a local neighborhood) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, b, c, "B-C") * }) * * const result = Graph.neighborhood(graph, 1, { radius: 1 }) * * Graph.nodeCount(result) // => 2 * ``` * * @see {@link inducedSubgraph} for selecting nodes while preserving identifiers * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, nodeIndex: NodeIndex, options?: NeighborhoodConfig): Graph; }; /** * Returns the subgraph induced by a collection of node indices. * * **When to use** * * Use when selecting an exact node set while preserving its active node and * edge identifiers. * * **Details** * * Node and edge indices are preserved. Duplicate input indices are ignored, * output ordering follows the original graph, and every edge whose endpoints * are both selected is retained. * * **Gotchas** * * Throws a `GraphError` when a selected node does not exist. * * @see {@link neighborhood} for selecting nodes by traversal distance * * @stability unstable * @category set operations * @since 4.0.0 */ export declare const inducedSubgraph: { /** * Returns the subgraph induced by a collection of node indices. * * **When to use** * * Use when selecting an exact node set while preserving its active node and * edge identifiers. * * **Details** * * Node and edge indices are preserved. Duplicate input indices are ignored, * output ordering follows the original graph, and every edge whose endpoints * are both selected is retained. * * **Gotchas** * * Throws a `GraphError` when a selected node does not exist. * * @see {@link neighborhood} for selecting nodes by traversal distance * * @stability unstable * @category set operations * @since 4.0.0 */ (nodeIndices: Iterable): (self: Graph) => Graph; /** * Returns the subgraph induced by a collection of node indices. * * **When to use** * * Use when selecting an exact node set while preserving its active node and * edge identifiers. * * **Details** * * Node and edge indices are preserved. Duplicate input indices are ignored, * output ordering follows the original graph, and every edge whose endpoints * are both selected is retained. * * **Gotchas** * * Throws a `GraphError` when a selected node does not exist. * * @see {@link neighborhood} for selecting nodes by traversal distance * * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, nodeIndices: Iterable): Graph; }; /** * Returns the disjoint union of two graphs. * * **When to use** * * Use when combining graphs while keeping every node distinct, even when node * payloads are equal. * * **Details** * * Copies all nodes and edges from both graphs without merging equal node data. * The result has the same graph kind as `self`. Throws a `GraphError` when the * graph kinds do not match. * * `G1 + G2 = {disjoint V1 + V2, disjoint E1 + E2}` * * **Gotchas** * * All node and edge identifiers are newly allocated. * * @see {@link compose} for merging overlapping logical nodes by identity * * @stability unstable * @category set operations * @since 4.0.0 */ export declare const sum: { /** * Returns the disjoint union of two graphs. * * **When to use** * * Use when combining graphs while keeping every node distinct, even when node * payloads are equal. * * **Details** * * Copies all nodes and edges from both graphs without merging equal node data. * The result has the same graph kind as `self`. Throws a `GraphError` when the * graph kinds do not match. * * `G1 + G2 = {disjoint V1 + V2, disjoint E1 + E2}` * * **Gotchas** * * All node and edge identifiers are newly allocated. * * @see {@link compose} for merging overlapping logical nodes by identity * * @stability unstable * @category set operations * @since 4.0.0 */ (that: Graph): (self: Graph>) => Graph; /** * Returns the disjoint union of two graphs. * * **When to use** * * Use when combining graphs while keeping every node distinct, even when node * payloads are equal. * * **Details** * * Copies all nodes and edges from both graphs without merging equal node data. * The result has the same graph kind as `self`. Throws a `GraphError` when the * graph kinds do not match. * * `G1 + G2 = {disjoint V1 + V2, disjoint E1 + E2}` * * **Gotchas** * * All node and edge identifiers are newly allocated. * * @see {@link compose} for merging overlapping logical nodes by identity * * @stability unstable * @category set operations * @since 4.0.0 */ (self: Graph, that: Graph>): Graph; }; /** * Adds a new node to a mutable graph and returns its index. * * **When to use** * * Use to allocate a new node in a mutable graph before storing edges or * querying it by index. * * **Details** * * The returned index is allocated from the graph's next node index. The mutable * graph stores the node data and initializes empty incoming and outgoing edge * indexes for the new node. * * **Gotchas** * * `NodeIndex` values are identifiers and are not reused after removals. * * **Example** (Adding nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") // => 0 * Graph.addNode(mutable, "Node B") // => 1 * }) * ``` * * @see {@link mutate} for obtaining a mutable graph from an immutable graph * @see {@link addEdge} for connecting existing nodes * * @stability unstable * @category mutations * @since 3.18.0 */ export declare const addNode: (mutable: MutableGraph, data: N) => NodeIndex; /** * Gets the data associated with a node index safely, if it exists. * * **Example** (Getting node data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * }) * * Graph.getNode(graph, 0) // => Option.some("Node A") * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const getNode: { /** * Gets the data associated with a node index safely, if it exists. * * **Example** (Getting node data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * }) * * Graph.getNode(graph, 0) // => Option.some("Node A") * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => Option.Option; /** * Gets the data associated with a node index safely, if it exists. * * **Example** (Getting node data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * }) * * Graph.getNode(graph, 0) // => Option.some("Node A") * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): Option.Option; }; /** * Checks whether a node with the given index exists in the graph. * * **Example** (Checking node existence) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * }) * * Graph.hasNode(graph, 0) // => true * Graph.hasNode(graph, 999) // => false * ``` * * @stability unstable * @category predicates * @since 3.18.0 */ export declare const hasNode: { /** * Checks whether a node with the given index exists in the graph. * * **Example** (Checking node existence) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * }) * * Graph.hasNode(graph, 0) // => true * Graph.hasNode(graph, 999) // => false * ``` * * @stability unstable * @category predicates * @since 3.18.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => boolean; /** * Checks whether a node with the given index exists in the graph. * * **Example** (Checking node existence) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * }) * * Graph.hasNode(graph, 0) // => true * Graph.hasNode(graph, 999) // => false * ``` * * @stability unstable * @category predicates * @since 3.18.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): boolean; }; /** * Returns the number of nodes in the graph. * * **Example** (Counting nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const emptyGraph = Graph.directed() * Graph.nodeCount(emptyGraph) // => 0 * * const graphWithNodes = Graph.mutate(emptyGraph, (mutable) => { * Graph.addNode(mutable, "Node A") * Graph.addNode(mutable, "Node B") * Graph.addNode(mutable, "Node C") * }) * * Graph.nodeCount(graphWithNodes) // => 3 * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const nodeCount: (graph: Graph | MutableGraph) => number; /** * Finds the first node that matches the given predicate. * * **Example** (Finding the first matching node) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * Graph.addNode(mutable, "Node B") * Graph.addNode(mutable, "Node C") * }) * * Graph.findNode(graph, (data) => data.startsWith("Node B")) // => Option.some(1) * Graph.findNode(graph, (data) => data === "Node D") // => Option.none() * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const findNode: { /** * Finds the first node that matches the given predicate. * * **Example** (Finding the first matching node) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * Graph.addNode(mutable, "Node B") * Graph.addNode(mutable, "Node C") * }) * * Graph.findNode(graph, (data) => data.startsWith("Node B")) // => Option.some(1) * Graph.findNode(graph, (data) => data === "Node D") // => Option.none() * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (predicate: (data: N) => boolean): (graph: Graph | MutableGraph) => Option.Option; /** * Finds the first node that matches the given predicate. * * **Example** (Finding the first matching node) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Node A") * Graph.addNode(mutable, "Node B") * Graph.addNode(mutable, "Node C") * }) * * Graph.findNode(graph, (data) => data.startsWith("Node B")) // => Option.some(1) * Graph.findNode(graph, (data) => data === "Node D") // => Option.none() * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, predicate: (data: N) => boolean): Option.Option; }; /** * Finds all nodes that match the given predicate. * * **Example** (Finding matching nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Start A") * Graph.addNode(mutable, "Node B") * Graph.addNode(mutable, "Start C") * }) * * Graph.findNodes(graph, (data) => data.startsWith("Start")) // => [0, 2] * Graph.findNodes(graph, (data) => data === "Not Found") // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const findNodes: { /** * Finds all nodes that match the given predicate. * * **Example** (Finding matching nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Start A") * Graph.addNode(mutable, "Node B") * Graph.addNode(mutable, "Start C") * }) * * Graph.findNodes(graph, (data) => data.startsWith("Start")) // => [0, 2] * Graph.findNodes(graph, (data) => data === "Not Found") // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (predicate: (data: N) => boolean): (graph: Graph | MutableGraph) => Array; /** * Finds all nodes that match the given predicate. * * **Example** (Finding matching nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * Graph.addNode(mutable, "Start A") * Graph.addNode(mutable, "Node B") * Graph.addNode(mutable, "Start C") * }) * * Graph.findNodes(graph, (data) => data.startsWith("Start")) // => [0, 2] * Graph.findNodes(graph, (data) => data === "Not Found") // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, predicate: (data: N) => boolean): Array; }; /** * Finds the first edge that matches the given predicate. * * **Example** (Finding the first matching edge) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 10) * Graph.addEdge(mutable, nodeB, nodeC, 20) * }) * * Graph.findEdge(graph, (data) => data > 15) // => Option.some(1) * Graph.findEdge(graph, (data) => data > 100) // => Option.none() * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const findEdge: { /** * Finds the first edge that matches the given predicate. * * **Example** (Finding the first matching edge) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 10) * Graph.addEdge(mutable, nodeB, nodeC, 20) * }) * * Graph.findEdge(graph, (data) => data > 15) // => Option.some(1) * Graph.findEdge(graph, (data) => data > 100) // => Option.none() * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): (graph: Graph | MutableGraph) => Option.Option; /** * Finds the first edge that matches the given predicate. * * **Example** (Finding the first matching edge) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 10) * Graph.addEdge(mutable, nodeB, nodeC, 20) * }) * * Graph.findEdge(graph, (data) => data > 15) // => Option.some(1) * Graph.findEdge(graph, (data) => data > 100) // => Option.none() * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): Option.Option; }; /** * Finds all edges that match the given predicate. * * **Example** (Finding matching edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 10) * Graph.addEdge(mutable, nodeB, nodeC, 20) * Graph.addEdge(mutable, nodeC, nodeA, 30) * }) * * Graph.findEdges(graph, (data) => data >= 20) // => [1, 2] * Graph.findEdges(graph, (data) => data > 100) // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const findEdges: { /** * Finds all edges that match the given predicate. * * **Example** (Finding matching edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 10) * Graph.addEdge(mutable, nodeB, nodeC, 20) * Graph.addEdge(mutable, nodeC, nodeA, 30) * }) * * Graph.findEdges(graph, (data) => data >= 20) // => [1, 2] * Graph.findEdges(graph, (data) => data > 100) // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): (graph: Graph | MutableGraph) => Array; /** * Finds all edges that match the given predicate. * * **Example** (Finding matching edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 10) * Graph.addEdge(mutable, nodeB, nodeC, 20) * Graph.addEdge(mutable, nodeC, nodeA, 30) * }) * * Graph.findEdges(graph, (data) => data >= 20) // => [1, 2] * Graph.findEdges(graph, (data) => data > 100) // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): Array; }; /** * Updates a single node's data by applying a transformation function. * * **When to use** * * Use when replacing one node payload while preserving its identifier and * incident edges. * * **Gotchas** * * A missing node index is ignored. The transformation may query the graph, but * cannot mutate or finalize the same graph while it runs. * * **Example** (Updating node data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * Graph.addNode(mutable, "Node A") * Graph.addNode(mutable, "Node B") * Graph.updateNode(mutable, 0, (data) => data.toUpperCase()) * }) * * Graph.getNode(graph, 0) // => Option.some("NODE A") * ``` * * @stability unstable * @category transforming * @since 3.18.0 */ export declare const updateNode: (mutable: MutableGraph, index: NodeIndex, f: (data: N) => N) => void; /** * Updates a single edge's data by applying a transformation function. * * **When to use** * * Use when replacing one edge payload while preserving its identifier and * endpoints. * * **Gotchas** * * A missing edge index is ignored. The transformation may query the graph, but * cannot mutate or finalize the same graph while it runs. * * **Example** (Updating edge data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const result = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const edgeIndex = Graph.addEdge(mutable, nodeA, nodeB, 10) * Graph.updateEdge(mutable, edgeIndex, (data) => data * 2) * }) * * Option.map(Graph.getEdge(result, 0), (edge) => edge.data) // => Option.some(20) * ``` * * @stability unstable * @category transforming * @since 3.18.0 */ export declare const updateEdge: (mutable: MutableGraph, edgeIndex: EdgeIndex, f: (data: E) => E) => void; /** * Transforms every node's data in a mutable graph in place using the provided * mapping function. * * **When to use** * * Use when updating every node payload without changing graph structure. * * **Details** * * Node indices and edges are preserved; only the stored node data is replaced. * * **Gotchas** * * This function mutates in place, returns `void`, and cannot change the node * payload type. The mapping function may query the graph, but cannot mutate or * finalize the same graph while it runs. * * **Example** (Mapping node data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * Graph.addNode(mutable, "node a") * Graph.addNode(mutable, "node b") * Graph.addNode(mutable, "node c") * Graph.mapNodes(mutable, (data) => data.toUpperCase()) * }) * * Graph.getNode(graph, 0) // => Option.some("NODE A") * ``` * * @see {@link updateNode} for updating one node * @see {@link filterMapNodes} for mapping while removing nodes * @stability unstable * @category mapping * @since 3.18.0 */ export declare const mapNodes: (mutable: MutableGraph, f: (data: N) => N) => void; /** * Transforms every edge payload in a mutable graph in place. * * **When to use** * * Use when updating every edge payload without changing graph structure. * * **Details** * * Edge identifiers and endpoints are preserved. * * **Gotchas** * * This function mutates in place, returns `void`, and cannot change the edge * payload type. The mapping function may query the graph, but cannot mutate or * finalize the same graph while it runs. * * **Example** (Mapping edge data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 10) * Graph.addEdge(mutable, b, c, 20) * Graph.mapEdges(mutable, (data) => data * 2) * }) * * Option.map(Graph.getEdge(graph, 0), (edge) => edge.data) // => Option.some(20) * ``` * * @see {@link updateEdge} for updating one edge * @see {@link filterMapEdges} for mapping while removing edges * @stability unstable * @category mapping * @since 3.18.0 */ export declare const mapEdges: (mutable: MutableGraph, f: (data: E) => E) => void; /** * Swaps source and target nodes for every edge in a mutable graph. * * **When to use** * * Use when reversing every relationship in a directed graph, such as creating * a dependency transpose. * * **Details** * * Edge identifiers and payloads are preserved. * * **Gotchas** * * This operation is a no-op for undirected graphs. * * **Example** (Reversing edge directions) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) // A -> B * Graph.addEdge(mutable, b, c, 2) // B -> C * Graph.reverse(mutable) // Now B -> A, C -> B * }) * * Option.map(Graph.getEdge(graph, 0), (edge) => edge.source) // => Option.some(1) * ``` * * @stability unstable * @category transforming * @since 3.18.0 */ export declare const reverse: (mutable: MutableGraph) => void; /** * Filters and optionally transforms nodes in a mutable graph using a predicate function. * Nodes that return Option.none are removed along with all their connected edges. * * **Gotchas** * * The function may query the graph, but cannot mutate or finalize the same * graph while it runs. Retained payloads must remain the same node type. * * **Example** (Filtering and mapping nodes) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "active") * const b = Graph.addNode(mutable, "inactive") * const c = Graph.addNode(mutable, "active") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 2) * * // Keep only "active" nodes and transform to uppercase * Graph.filterMapNodes( * mutable, * (data) => * data === "active" ? Option.some(data.toUpperCase()) : Option.none() * ) * }) * * Graph.nodeCount(graph) // => 2 * ``` * * @stability unstable * @category filtering * @since 3.18.0 */ export declare const filterMapNodes: (mutable: MutableGraph, f: (data: N) => Option.Option) => void; /** * Filters and optionally transforms edges in a mutable graph using a predicate function. * Edges that return Option.none are removed from the graph. * * **Gotchas** * * The function may query the graph, but cannot mutate or finalize the same * graph while it runs. Retained payloads must remain the same edge type. * * **Example** (Filtering and mapping edges) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 5) * Graph.addEdge(mutable, b, c, 15) * Graph.addEdge(mutable, c, a, 25) * * // Keep only edges with weight >= 10 and double their weight * Graph.filterMapEdges( * mutable, * (data) => data >= 10 ? Option.some(data * 2) : Option.none() * ) * }) * * Graph.edgeCount(graph) // => 2 * ``` * * @stability unstable * @category filtering * @since 3.18.0 */ export declare const filterMapEdges: (mutable: MutableGraph, f: (data: E) => Option.Option) => void; /** * Filters nodes by removing those that don't match the predicate. * This function modifies the mutable graph in place. * Removed nodes also remove all incident edges; retained node identifiers are * preserved. * * **Gotchas** * * The predicate may query the graph, but cannot mutate or finalize the same * graph while it runs. * * **Example** (Filtering nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * Graph.addNode(mutable, "active") * Graph.addNode(mutable, "inactive") * Graph.addNode(mutable, "pending") * Graph.addNode(mutable, "active") * * // Keep only "active" nodes * Graph.filterNodes(mutable, (data) => data === "active") * }) * * Graph.nodeCount(graph) // => 2 * ``` * * @stability unstable * @category filtering * @since 3.18.0 */ export declare const filterNodes: (mutable: MutableGraph, predicate: (data: N) => boolean) => void; /** * Filters edges by removing those that don't match the predicate. * This function modifies the mutable graph in place. * Nodes are retained even when removing edges leaves them isolated. * * **Gotchas** * * The predicate may query the graph, but cannot mutate or finalize the same * graph while it runs. * * **Example** (Filtering edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * * Graph.addEdge(mutable, a, b, 5) * Graph.addEdge(mutable, b, c, 15) * Graph.addEdge(mutable, c, a, 25) * * // Keep only edges with weight >= 10 * Graph.filterEdges(mutable, (data) => data >= 10) * }) * * Graph.edgeCount(graph) // => 2 * ``` * * @stability unstable * @category filtering * @since 3.18.0 */ export declare const filterEdges: (mutable: MutableGraph, predicate: (data: E) => boolean) => void; /** * Adds a new edge to a mutable graph and returns its index. * * **When to use** * * Use to connect two existing nodes in a mutable graph while storing edge data * and receiving the new edge identifier. * * **Details** * * Self-loops and parallel edges are allowed. Undirected graphs retain the * supplied source and target orientation in the stored `Edge`, while traversal * and neighbor queries treat the connection as bidirectional. * * **Gotchas** * * The source and target nodes must already exist in the mutable graph; missing * endpoints throw a `GraphError`. * * **Example** (Adding edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * Graph.addEdge(mutable, nodeA, nodeB, 42) // => 0 * }) * ``` * * @see {@link mutate} for obtaining a mutable graph from an immutable graph * @see {@link addNode} for creating node indexes before connecting them * * @stability unstable * @category mutations * @since 3.18.0 */ export declare const addEdge: (mutable: MutableGraph, source: NodeIndex, target: NodeIndex, data: E) => EdgeIndex; /** * Removes a node and all its incident edges from a mutable graph. * * **Gotchas** * * A missing node index is ignored. * * **Example** (Removing a node) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const result = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * Graph.addEdge(mutable, nodeA, nodeB, 42) * * // Remove nodeA and all edges connected to it * Graph.removeNode(mutable, nodeA) * }) * Array.of(Graph.nodeCount(result), Graph.edgeCount(result)) // => [1, 0] * ``` * * @stability unstable * @category mutations * @since 3.18.0 */ export declare const removeNode: (mutable: MutableGraph, nodeIndex: NodeIndex) => void; /** * Removes multiple nodes and all their incident edges from a mutable graph. * * **When to use** * * Use when deleting a collection of nodes in one mutation pass. * * **Details** * * The input is collected before mutation, so it may be backed by an iterator * over the same graph. * * **Gotchas** * * Missing and duplicate node indices are ignored. Removing a node also removes * all of its incident edges. * * @see {@link removeNode} for removing one node * * @stability unstable * @category mutations * @since 4.0.0 */ export declare const removeNodes: (mutable: MutableGraph, nodeIndices: Iterable) => void; /** * Removes an edge from a mutable graph. * * **Gotchas** * * A missing edge index is ignored. * * **Example** (Removing an edge) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const result = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const edge = Graph.addEdge(mutable, nodeA, nodeB, 42) * * // Remove the edge * Graph.removeEdge(mutable, edge) * }) * Array.of(Graph.nodeCount(result), Graph.edgeCount(result)) // => [2, 0] * ``` * * @stability unstable * @category mutations * @since 3.18.0 */ export declare const removeEdge: (mutable: MutableGraph, edgeIndex: EdgeIndex) => void; /** * Removes multiple edges from a mutable graph. * * **When to use** * * Use when deleting a collection of edges in one mutation pass. * * **Details** * * The input is collected before mutation, so it may be backed by an iterator * over the same graph. * * **Gotchas** * * Missing and duplicate edge indices are ignored. Nodes are never removed. * * @see {@link removeEdge} for removing one edge * * @stability unstable * @category mutations * @since 4.0.0 */ export declare const removeEdges: (mutable: MutableGraph, edgeIndices: Iterable) => void; /** * Gets the edge data associated with an edge index safely, if it exists. * * **Example** (Getting edge data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * Graph.addEdge(mutable, nodeA, nodeB, 42) * }) * * Graph.getEdge(graph, 0) // => Option.some({ source: 0, target: 1, data: 42 }) * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const getEdge: { /** * Gets the edge data associated with an edge index safely, if it exists. * * **Example** (Getting edge data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * Graph.addEdge(mutable, nodeA, nodeB, 42) * }) * * Graph.getEdge(graph, 0) // => Option.some({ source: 0, target: 1, data: 42 }) * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (edgeIndex: EdgeIndex): (graph: Graph | MutableGraph) => Option.Option>; /** * Gets the edge data associated with an edge index safely, if it exists. * * **Example** (Getting edge data) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * Graph.addEdge(mutable, nodeA, nodeB, 42) * }) * * Graph.getEdge(graph, 0) // => Option.some({ source: 0, target: 1, data: 42 }) * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, edgeIndex: EdgeIndex): Option.Option>; }; /** * Checks whether an edge exists between two nodes in the graph. * * **Details** * * Directed graphs test only `source` to `target`; undirected graphs accept * either stored orientation. Parallel edges still produce one boolean result. * * **Gotchas** * * Returns `false` when either node does not exist. * * **Example** (Checking edge existence) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 42) * }) * * Graph.hasEdge(graph, 0, 1) // => true * Graph.hasEdge(graph, 0, 2) // => false * ``` * * @see {@link edgesBetween} for all matching edge identifiers * @stability unstable * @category predicates * @since 3.18.0 */ export declare const hasEdge: { /** * Checks whether an edge exists between two nodes in the graph. * * **Details** * * Directed graphs test only `source` to `target`; undirected graphs accept * either stored orientation. Parallel edges still produce one boolean result. * * **Gotchas** * * Returns `false` when either node does not exist. * * **Example** (Checking edge existence) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 42) * }) * * Graph.hasEdge(graph, 0, 1) // => true * Graph.hasEdge(graph, 0, 2) // => false * ``` * * @see {@link edgesBetween} for all matching edge identifiers * @stability unstable * @category predicates * @since 3.18.0 */ (source: NodeIndex, target: NodeIndex): (graph: Graph | MutableGraph) => boolean; /** * Checks whether an edge exists between two nodes in the graph. * * **Details** * * Directed graphs test only `source` to `target`; undirected graphs accept * either stored orientation. Parallel edges still produce one boolean result. * * **Gotchas** * * Returns `false` when either node does not exist. * * **Example** (Checking edge existence) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 42) * }) * * Graph.hasEdge(graph, 0, 1) // => true * Graph.hasEdge(graph, 0, 2) // => false * ``` * * @see {@link edgesBetween} for all matching edge identifiers * @stability unstable * @category predicates * @since 3.18.0 */ (graph: Graph | MutableGraph, source: NodeIndex, target: NodeIndex): boolean; }; /** * Returns the number of edges in the graph. * * **Example** (Counting edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const emptyGraph = Graph.directed() * Graph.edgeCount(emptyGraph) // => 0 * * const graphWithEdges = Graph.mutate(emptyGraph, (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 1) * Graph.addEdge(mutable, nodeB, nodeC, 2) * Graph.addEdge(mutable, nodeC, nodeA, 3) * }) * * Graph.edgeCount(graphWithEdges) // => 3 * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const edgeCount: (graph: Graph | MutableGraph) => number; /** * Returns the indices of all edges incident to a node. * * **Details** * * Each edge is returned once in graph edge order, including self-loops. * Throws a `GraphError` when the node does not exist. * * @stability unstable * @category getters * @since 4.0.0 */ export declare const incidentEdges: { /** * Returns the indices of all edges incident to a node. * * **Details** * * Each edge is returned once in graph edge order, including self-loops. * Throws a `GraphError` when the node does not exist. * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => Array; /** * Returns the indices of all edges incident to a node. * * **Details** * * Each edge is returned once in graph edge order, including self-loops. * Throws a `GraphError` when the node does not exist. * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): Array; }; /** * Returns the indices of outgoing edges for a node in a directed graph. * * **Details** * * Parallel edges and self-loops are returned separately in adjacency order. * Throws a `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ export declare const outgoingEdges: { /** * Returns the indices of outgoing edges for a node in a directed graph. * * **Details** * * Parallel edges and self-loops are returned separately in adjacency order. * Throws a `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => Array; /** * Returns the indices of outgoing edges for a node in a directed graph. * * **Details** * * Parallel edges and self-loops are returned separately in adjacency order. * Throws a `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): Array; }; /** * Returns the indices of incoming edges for a node in a directed graph. * * **Details** * * Parallel edges and self-loops are returned separately in reverse-adjacency * order. Throws a `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ export declare const incomingEdges: { /** * Returns the indices of incoming edges for a node in a directed graph. * * **Details** * * Parallel edges and self-loops are returned separately in reverse-adjacency * order. Throws a `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => Array; /** * Returns the indices of incoming edges for a node in a directed graph. * * **Details** * * Parallel edges and self-loops are returned separately in reverse-adjacency * order. Throws a `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): Array; }; /** * Returns all edge indices connecting the supplied nodes. * * **Details** * * Directed graphs only include edges from `source` to `target`; undirected * graphs include either stored orientation. Parallel edges are retained. * Throws a `GraphError` when either node does not exist. * * @stability unstable * @category getters * @since 4.0.0 */ export declare const edgesBetween: { /** * Returns all edge indices connecting the supplied nodes. * * **Details** * * Directed graphs only include edges from `source` to `target`; undirected * graphs include either stored orientation. Parallel edges are retained. * Throws a `GraphError` when either node does not exist. * * @stability unstable * @category getters * @since 4.0.0 */ (source: NodeIndex, target: NodeIndex): (graph: Graph | MutableGraph) => Array; /** * Returns all edge indices connecting the supplied nodes. * * **Details** * * Directed graphs only include edges from `source` to `target`; undirected * graphs include either stored orientation. Parallel edges are retained. * Throws a `GraphError` when either node does not exist. * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, source: NodeIndex, target: NodeIndex): Array; }; /** * Returns the degree of a node in an undirected graph. * * **Details** * * Parallel edges count separately and a self-loop contributes two. Throws a * `GraphError` for a directed graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ export declare const degree: { /** * Returns the degree of a node in an undirected graph. * * **Details** * * Parallel edges count separately and a self-loop contributes two. Throws a * `GraphError` for a directed graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => number; /** * Returns the degree of a node in an undirected graph. * * **Details** * * Parallel edges count separately and a self-loop contributes two. Throws a * `GraphError` for a directed graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): number; }; /** * Returns the out-degree of a node in a directed graph. * * **Details** * * Parallel edges count separately and a self-loop contributes one. Throws a * `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ export declare const outDegree: { /** * Returns the out-degree of a node in a directed graph. * * **Details** * * Parallel edges count separately and a self-loop contributes one. Throws a * `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => number; /** * Returns the out-degree of a node in a directed graph. * * **Details** * * Parallel edges count separately and a self-loop contributes one. Throws a * `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): number; }; /** * Returns the in-degree of a node in a directed graph. * * **Details** * * Parallel edges count separately and a self-loop contributes one. Throws a * `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ export declare const inDegree: { /** * Returns the in-degree of a node in a directed graph. * * **Details** * * Parallel edges count separately and a self-loop contributes one. Throws a * `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => number; /** * Returns the in-degree of a node in a directed graph. * * **Details** * * Parallel edges count separately and a self-loop contributes one. Throws a * `GraphError` for an undirected graph or missing node. * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): number; }; /** * Returns the neighboring node indices for a node. * * **Details** * * For directed graphs, neighbors are the targets of outgoing edges. For * undirected graphs, neighbors are the other endpoints of incident edges. * Each neighbor appears once in first edge occurrence order, including the * queried node when it has a self-loop. * * **Gotchas** * * Returns an empty array when the node does not exist. For directed graphs, * use `predecessors` when incoming neighbors are required. * * **Example** (Getting outgoing neighbors) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 1) * Graph.addEdge(mutable, nodeA, nodeC, 2) * }) * * Graph.neighbors(graph, 0) // => [1, 2] * Graph.neighbors(graph, 1) // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ export declare const neighbors: { /** * Returns the neighboring node indices for a node. * * **Details** * * For directed graphs, neighbors are the targets of outgoing edges. For * undirected graphs, neighbors are the other endpoints of incident edges. * Each neighbor appears once in first edge occurrence order, including the * queried node when it has a self-loop. * * **Gotchas** * * Returns an empty array when the node does not exist. For directed graphs, * use `predecessors` when incoming neighbors are required. * * **Example** (Getting outgoing neighbors) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 1) * Graph.addEdge(mutable, nodeA, nodeC, 2) * }) * * Graph.neighbors(graph, 0) // => [1, 2] * Graph.neighbors(graph, 1) // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => Array; /** * Returns the neighboring node indices for a node. * * **Details** * * For directed graphs, neighbors are the targets of outgoing edges. For * undirected graphs, neighbors are the other endpoints of incident edges. * Each neighbor appears once in first edge occurrence order, including the * queried node when it has a self-loop. * * **Gotchas** * * Returns an empty array when the node does not exist. For directed graphs, * use `predecessors` when incoming neighbors are required. * * **Example** (Getting outgoing neighbors) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 1) * Graph.addEdge(mutable, nodeA, nodeC, 2) * }) * * Graph.neighbors(graph, 0) // => [1, 2] * Graph.neighbors(graph, 1) // => [] * ``` * * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): Array; }; /** * Returns the outgoing neighbor node indices for a node in a directed graph. * * **When to use** * * Use when you need the nodes reached by following outgoing edges from a node in * a directed graph. * * Each node appears once in first outgoing edge occurrence order. A self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. A missing node * returns an empty array. * * @see {@link predecessors} for incoming neighbors in a directed graph * @see {@link neighbors} for generic neighbor lookup across graph kinds * * @stability unstable * @category getters * @since 4.0.0 */ export declare const successors: { /** * Returns the outgoing neighbor node indices for a node in a directed graph. * * **When to use** * * Use when you need the nodes reached by following outgoing edges from a node in * a directed graph. * * Each node appears once in first outgoing edge occurrence order. A self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. A missing node * returns an empty array. * * @see {@link predecessors} for incoming neighbors in a directed graph * @see {@link neighbors} for generic neighbor lookup across graph kinds * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => Array; /** * Returns the outgoing neighbor node indices for a node in a directed graph. * * **When to use** * * Use when you need the nodes reached by following outgoing edges from a node in * a directed graph. * * Each node appears once in first outgoing edge occurrence order. A self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. A missing node * returns an empty array. * * @see {@link predecessors} for incoming neighbors in a directed graph * @see {@link neighbors} for generic neighbor lookup across graph kinds * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): Array; }; /** * Returns the incoming neighbor node indices for a node in a directed graph. * * **When to use** * * Use when you need the nodes that reach a node by following incoming edges in a * directed graph. * * Each node appears once in first incoming edge occurrence order. A self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. A missing node * returns an empty array. * * @see {@link successors} for outgoing neighbors in a directed graph * @see {@link neighbors} for generic neighbor lookup across graph kinds * * @stability unstable * @category getters * @since 4.0.0 */ export declare const predecessors: { /** * Returns the incoming neighbor node indices for a node in a directed graph. * * **When to use** * * Use when you need the nodes that reach a node by following incoming edges in a * directed graph. * * Each node appears once in first incoming edge occurrence order. A self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. A missing node * returns an empty array. * * @see {@link successors} for outgoing neighbors in a directed graph * @see {@link neighbors} for generic neighbor lookup across graph kinds * * @stability unstable * @category getters * @since 4.0.0 */ (nodeIndex: NodeIndex): (graph: Graph | MutableGraph) => Array; /** * Returns the incoming neighbor node indices for a node in a directed graph. * * **When to use** * * Use when you need the nodes that reach a node by following incoming edges in a * directed graph. * * Each node appears once in first incoming edge occurrence order. A self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. A missing node * returns an empty array. * * @see {@link successors} for outgoing neighbors in a directed graph * @see {@link neighbors} for generic neighbor lookup across graph kinds * * @stability unstable * @category getters * @since 4.0.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex): Array; }; /** * Gets directed neighbors of a node in a specific direction. * * **When to use** * * Use when maintaining existing code that already passes an explicit traversal * direction. New code should prefer `successors` or `predecessors`. * Results contain each node once in first edge occurrence order, and a self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. * * **Example** (Traversing directed neighbors) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "A->B") * }) * * const nodeA = 0 * const nodeB = 1 * * // Get outgoing neighbors (nodes that nodeA points to) * const outgoing = Graph.neighborsDirected(graph, nodeA, "outgoing") * * // Get incoming neighbors (nodes that point to nodeB) * const incoming = Graph.neighborsDirected(graph, nodeB, "incoming") * Array.of(outgoing, incoming) // => [[1], [0]] * ``` * * @deprecated Use {@link successors} for outgoing neighbors or {@link predecessors} for incoming neighbors. * @see {@link successors} for outgoing neighbors in a directed graph * @see {@link predecessors} for incoming neighbors in a directed graph * @stability unstable * @category getters * @since 3.18.0 */ export declare const neighborsDirected: { /** * Gets directed neighbors of a node in a specific direction. * * **When to use** * * Use when maintaining existing code that already passes an explicit traversal * direction. New code should prefer `successors` or `predecessors`. * Results contain each node once in first edge occurrence order, and a self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. * * **Example** (Traversing directed neighbors) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "A->B") * }) * * const nodeA = 0 * const nodeB = 1 * * // Get outgoing neighbors (nodes that nodeA points to) * const outgoing = Graph.neighborsDirected(graph, nodeA, "outgoing") * * // Get incoming neighbors (nodes that point to nodeB) * const incoming = Graph.neighborsDirected(graph, nodeB, "incoming") * Array.of(outgoing, incoming) // => [[1], [0]] * ``` * * @deprecated Use {@link successors} for outgoing neighbors or {@link predecessors} for incoming neighbors. * @see {@link successors} for outgoing neighbors in a directed graph * @see {@link predecessors} for incoming neighbors in a directed graph * @stability unstable * @category getters * @since 3.18.0 */ (nodeIndex: NodeIndex, direction: Direction): (graph: Graph | MutableGraph) => Array; /** * Gets directed neighbors of a node in a specific direction. * * **When to use** * * Use when maintaining existing code that already passes an explicit traversal * direction. New code should prefer `successors` or `predecessors`. * Results contain each node once in first edge occurrence order, and a self-loop * contributes the queried node once. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. * * **Example** (Traversing directed neighbors) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "A->B") * }) * * const nodeA = 0 * const nodeB = 1 * * // Get outgoing neighbors (nodes that nodeA points to) * const outgoing = Graph.neighborsDirected(graph, nodeA, "outgoing") * * // Get incoming neighbors (nodes that point to nodeB) * const incoming = Graph.neighborsDirected(graph, nodeB, "incoming") * Array.of(outgoing, incoming) // => [[1], [0]] * ``` * * @deprecated Use {@link successors} for outgoing neighbors or {@link predecessors} for incoming neighbors. * @see {@link successors} for outgoing neighbors in a directed graph * @see {@link predecessors} for incoming neighbors in a directed graph * @stability unstable * @category getters * @since 3.18.0 */ (graph: Graph | MutableGraph, nodeIndex: NodeIndex, direction: Direction): Array; }; /** * Configuration options for GraphViz DOT format generation from graphs. * * **When to use** * * Use when customizing labels or the graph name produced by `toGraphViz`. * * **Details** * * These options customize node labels, edge labels, and graph naming in DOT * format compatible with GraphViz tools. * * **Example** (Configuring GraphViz labels) * * ```ts import.meta.vitest * import type { Graph } from "effect" * * // Basic options with custom labels * const basicOptions: Graph.GraphVizOptions = { * nodeLabel: (data) => `Node: ${data}`, * edgeLabel: (data) => `Weight: ${data}` * } * * // Complete options with graph naming * const namedOptions: Graph.GraphVizOptions = { * nodeLabel: (data) => data.toUpperCase(), * edgeLabel: (data) => data, * graphName: "MyDependencyGraph" * } * Array.of(basicOptions.nodeLabel?.("A"), namedOptions.graphName) // => ["Node: A", "MyDependencyGraph"] * ``` * * @see {@link toGraphViz} for generating DOT output * @stability unstable * @category configuration * @since 3.18.0 */ export interface GraphVizOptions { /** * Function to generate custom labels for nodes. * Defaults to String(data) if not provided. */ readonly nodeLabel?: (data: N) => string; /** * Function to generate custom labels for edges. * Defaults to String(data) if not provided. */ readonly edgeLabel?: (data: E) => string; /** * Name for the DOT graph. * Defaults to "G" if not provided. */ readonly graphName?: string; } /** * Exports a graph to GraphViz DOT format for visualization. * * **When to use** * * Use when sending graph structure to GraphViz-compatible visualization or * documentation tools. * * **Example** (Exporting GraphViz DOT) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 1) * Graph.addEdge(mutable, nodeB, nodeC, 2) * Graph.addEdge(mutable, nodeC, nodeA, 3) * }) * * Graph.toGraphViz(graph).split("\n") // => ['digraph "G" {', ' "0" [label="Node A"];', ' "1" [label="Node B"];', ' "2" [label="Node C"];', ' "0" -> "1" [label="1"];', ' "1" -> "2" [label="2"];', ' "2" -> "0" [label="3"];', "}"] * ``` * * @see {@link toMermaid} for Mermaid diagram output * @stability unstable * @category converting * @since 3.18.0 */ export declare const toGraphViz: { /** * Exports a graph to GraphViz DOT format for visualization. * * **When to use** * * Use when sending graph structure to GraphViz-compatible visualization or * documentation tools. * * **Example** (Exporting GraphViz DOT) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 1) * Graph.addEdge(mutable, nodeB, nodeC, 2) * Graph.addEdge(mutable, nodeC, nodeA, 3) * }) * * Graph.toGraphViz(graph).split("\n") // => ['digraph "G" {', ' "0" [label="Node A"];', ' "1" [label="Node B"];', ' "2" [label="Node C"];', ' "0" -> "1" [label="1"];', ' "1" -> "2" [label="2"];', ' "2" -> "0" [label="3"];', "}"] * ``` * * @see {@link toMermaid} for Mermaid diagram output * @stability unstable * @category converting * @since 3.18.0 */ (options?: GraphVizOptions): (graph: Graph | MutableGraph) => string; /** * Exports a graph to GraphViz DOT format for visualization. * * **When to use** * * Use when sending graph structure to GraphViz-compatible visualization or * documentation tools. * * **Example** (Exporting GraphViz DOT) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.mutate(Graph.directed(), (mutable) => { * const nodeA = Graph.addNode(mutable, "Node A") * const nodeB = Graph.addNode(mutable, "Node B") * const nodeC = Graph.addNode(mutable, "Node C") * Graph.addEdge(mutable, nodeA, nodeB, 1) * Graph.addEdge(mutable, nodeB, nodeC, 2) * Graph.addEdge(mutable, nodeC, nodeA, 3) * }) * * Graph.toGraphViz(graph).split("\n") // => ['digraph "G" {', ' "0" [label="Node A"];', ' "1" [label="Node B"];', ' "2" [label="Node C"];', ' "0" -> "1" [label="1"];', ' "1" -> "2" [label="2"];', ' "2" -> "0" [label="3"];', "}"] * ``` * * @see {@link toMermaid} for Mermaid diagram output * @stability unstable * @category converting * @since 3.18.0 */ (graph: Graph | MutableGraph, options?: GraphVizOptions): string; }; /** * Mermaid node shape types for diagram visualization. * * **Details** * * Each shape produces different visual representations in Mermaid diagrams: * - `rectangle`: Standard rectangular nodes `A["label"]` * - `rounded`: Rounded rectangular nodes `A("label")` * - `circle`: Circular nodes `A(("label"))` * - `diamond`: Diamond-shaped nodes `A{"label"}` * - `hexagon`: Hexagonal nodes `A{{"label"}}` * - `stadium`: Stadium-shaped nodes `A(["label"])` * - `subroutine`: Subroutine-style nodes `A[["label"]]` * - `cylindrical`: Cylindrical database-style nodes `A[("label")]` * * **Example** (Selecting Mermaid node shapes) * * ```ts import.meta.vitest * import type { Graph } from "effect" * * // Shape selector function for different node types * const shapeSelector = (nodeData: string): Graph.MermaidNodeShape => { * if (nodeData.includes("start") || nodeData.includes("end")) return "circle" * if (nodeData.includes("decision")) return "diamond" * if (nodeData.includes("process")) return "rectangle" * if (nodeData.includes("data")) return "cylindrical" * return "rounded" * } * * const options: Graph.MermaidOptions = { * nodeShape: shapeSelector * } * options.nodeShape?.("decision") // => "diamond" * ``` * * @stability unstable * @category models * @since 3.18.0 */ export type MermaidNodeShape = "rectangle" | "rounded" | "circle" | "diamond" | "hexagon" | "stadium" | "subroutine" | "cylindrical"; /** * Mermaid diagram direction types for controlling layout orientation. * * **Details** * * Determines the flow direction of nodes and edges in the diagram: * - `TB`/`TD`: Top to Bottom (vertical layout, default) * - `BT`: Bottom to Top (reverse vertical) * - `LR`: Left to Right (horizontal layout) * - `RL`: Right to Left (reverse horizontal) * * **Example** (Configuring Mermaid directions) * * ```ts import.meta.vitest * import type { Graph } from "effect" * * // Horizontal workflow diagram * const horizontalOptions: Graph.MermaidOptions = { * direction: "LR" * } * * // Vertical hierarchy (default) * const verticalOptions: Graph.MermaidOptions = { * direction: "TB" * } * * // Bottom-up flow * const bottomUpOptions: Graph.MermaidOptions = { * direction: "BT" * } * Array.of(horizontalOptions.direction, verticalOptions.direction, bottomUpOptions.direction) // => ["LR", "TB", "BT"] * ``` * * @stability unstable * @category models * @since 3.18.0 */ export type MermaidDirection = "TB" | "TD" | "BT" | "RL" | "LR"; /** * Mermaid diagram types for different visualization formats. * * **Details** * * Specifies the Mermaid diagram syntax to use: * - `flowchart`: For directed graphs with arrows (`A --> B`) * - `graph`: For undirected graphs with lines (`A --- B`) * * When not specified, automatically selects based on graph type: * directed graphs use "flowchart", undirected graphs use "graph". * * **Example** (Selecting Mermaid diagram types) * * ```ts import.meta.vitest * import type { Graph } from "effect" * * // Force flowchart format (even for undirected graphs) * const flowchartOptions: Graph.MermaidOptions = { * diagramType: "flowchart" * } * * // Force graph format (shows undirected connections) * const graphOptions: Graph.MermaidOptions = { * diagramType: "graph" * } * * // Auto-detection (recommended, default behavior) * const autoOptions: Graph.MermaidOptions = {} * Array.of(flowchartOptions.diagramType, graphOptions.diagramType, autoOptions.diagramType) // => ["flowchart", "graph", undefined] * ``` * * @stability unstable * @category models * @since 3.18.0 */ export type MermaidDiagramType = "flowchart" | "graph"; /** * Configuration options for Mermaid diagram generation from graphs. * * **When to use** * * Use when customizing labels, layout, node shapes, or syntax emitted by * `toMermaid`. * * **Details** * * These options customize node labels, edge labels, diagram type, layout * direction and node shapes in Mermaid format. * * **Example** (Configuring Mermaid output) * * ```ts import.meta.vitest * import type { Graph } from "effect" * * // Basic options with custom labels * const basicOptions: Graph.MermaidOptions = { * nodeLabel: (data) => `Node: ${data}`, * edgeLabel: (data) => `Weight: ${data}` * } * * // Advanced options with all features * const advancedOptions: Graph.MermaidOptions = { * nodeLabel: (data) => data.toUpperCase(), * edgeLabel: (data) => data, * diagramType: "flowchart", * direction: "LR", * nodeShape: (data) => data.includes("start") ? "circle" : "rectangle" * } * Array.of(basicOptions.nodeLabel?.("A"), advancedOptions.nodeShape?.("start")) // => ["Node: A", "circle"] * ``` * * @see {@link toMermaid} for generating Mermaid output * @stability unstable * @category configuration * @since 3.18.0 */ export interface MermaidOptions { /** * Function to generate custom labels for nodes. * Defaults to String(data) if not provided. */ readonly nodeLabel?: (data: N) => string; /** * Function to generate custom labels for edges. * Defaults to String(data) if not provided. */ readonly edgeLabel?: (data: E) => string; /** * Diagram type override. If not specified, automatically detects: * - "flowchart" for directed graphs * - "graph" for undirected graphs */ readonly diagramType?: MermaidDiagramType; /** * Direction for diagram layout. * Defaults to "TD" (Top Down) if not provided. */ readonly direction?: MermaidDirection; /** * Function to determine node shape for each node. * Defaults to "rectangle" for all nodes if not provided. */ readonly nodeShape?: (data: N) => MermaidNodeShape; } /** * Exports a graph to Mermaid diagram format for visualization. * * **When to use** * * Use when embedding graph diagrams in Markdown, documentation sites, or other * Mermaid-compatible tools. * * **Details** * * Directed graphs default to `flowchart` with arrow edges, while undirected * graphs default to `graph` with line edges. Labels and node shapes can be * customized with `MermaidOptions`. * * **Example** (Exporting a Mermaid diagram) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const app = Graph.addNode(mutable, "App") * const database = Graph.addNode(mutable, "Database") * Graph.addEdge(mutable, app, database, "queries") * }) * * Graph.toMermaid(graph).split("\n") // => ["flowchart TD", ' 0["App"]', ' 1["Database"]', ' 0 -->|"queries"| 1'] * ``` * * @see {@link toGraphViz} for GraphViz DOT output * @stability unstable * @category converting * @since 3.18.0 */ export declare const toMermaid: { /** * Exports a graph to Mermaid diagram format for visualization. * * **When to use** * * Use when embedding graph diagrams in Markdown, documentation sites, or other * Mermaid-compatible tools. * * **Details** * * Directed graphs default to `flowchart` with arrow edges, while undirected * graphs default to `graph` with line edges. Labels and node shapes can be * customized with `MermaidOptions`. * * **Example** (Exporting a Mermaid diagram) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const app = Graph.addNode(mutable, "App") * const database = Graph.addNode(mutable, "Database") * Graph.addEdge(mutable, app, database, "queries") * }) * * Graph.toMermaid(graph).split("\n") // => ["flowchart TD", ' 0["App"]', ' 1["Database"]', ' 0 -->|"queries"| 1'] * ``` * * @see {@link toGraphViz} for GraphViz DOT output * @stability unstable * @category converting * @since 3.18.0 */ (options?: MermaidOptions): (graph: Graph | MutableGraph) => string; /** * Exports a graph to Mermaid diagram format for visualization. * * **When to use** * * Use when embedding graph diagrams in Markdown, documentation sites, or other * Mermaid-compatible tools. * * **Details** * * Directed graphs default to `flowchart` with arrow edges, while undirected * graphs default to `graph` with line edges. Labels and node shapes can be * customized with `MermaidOptions`. * * **Example** (Exporting a Mermaid diagram) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const app = Graph.addNode(mutable, "App") * const database = Graph.addNode(mutable, "Database") * Graph.addEdge(mutable, app, database, "queries") * }) * * Graph.toMermaid(graph).split("\n") // => ["flowchart TD", ' 0["App"]', ' 1["Database"]', ' 0 -->|"queries"| 1'] * ``` * * @see {@link toGraphViz} for GraphViz DOT output * @stability unstable * @category converting * @since 3.18.0 */ (graph: Graph | MutableGraph, options?: MermaidOptions): string; }; /** * Direction of directed edges relative to a node. * * **Details** * * `"outgoing"` selects edges whose source is the node, while `"incoming"` * selects edges whose target is the node. * * @stability unstable * @category models * @since 3.18.0 */ export type Direction = "outgoing" | "incoming"; /** * Controls how traversal follows directed edges. * * **Details** * * `"outgoing"` follows edges from source to target, `"incoming"` follows them * from target to source, and `"undirected"` allows traversal in either * direction. * * **Example** (Traversing by direction) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A-B") * Graph.addEdge(mutable, a, c, "A-C") * }) * * Array.from(Graph.indices(Graph.bfs(graph, { start: [0], direction: "outgoing" }))) // => [0, 1, 2] * Array.from(Graph.indices(Graph.bfs(graph, { start: [1], direction: "incoming" }))) // => [1, 0] * Array.from(Graph.indices(Graph.bfs(graph, { start: [1], direction: "undirected" }))) // => [1, 0, 2] * ``` * * @stability unstable * @category models * @since 4.0.0 */ export type TraversalDirection = Direction | "undirected"; /** * A cycle witness containing a closed node path and its traversed edges. * * **Details** * * `path` repeats its first node at the end, so `edges.length` is always * `path.length - 1`. * * @stability unstable * @category models * @since 4.0.0 */ export interface CycleResult { readonly path: Array; readonly edges: Array; } /** * Returns one cycle in a graph, if present. * * **When to use** * * Use when you need the nodes and edges of a concrete cycle for diagnostics or * reporting. * * **Details** * * Directed cycles respect edge orientation. A self-loop is represented as a * one-edge cycle, and two parallel undirected edges form a two-edge cycle. * * @see {@link isAcyclic} when only a boolean cycle check is needed * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const findCycle: (graph: Graph | MutableGraph) => Option.Option; /** * Checks whether the graph is acyclic (contains no cycles). * * **When to use** * * Use when validating that a graph contains no cycle and a cycle witness is * not needed. * * **Details** * * Directed cycles respect edge orientation. Self-loops are cycles, and two * parallel edges form a cycle in an undirected graph. * * **Example** (Checking cycles) * * ```ts import.meta.vitest * import { Graph } from "effect" * * // Acyclic directed graph (DAG) * const dag = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A->B") * Graph.addEdge(mutable, b, c, "B->C") * }) * Graph.isAcyclic(dag) // => true * * // Cyclic directed graph * const cyclic = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, "A->B") * Graph.addEdge(mutable, b, a, "B->A") // Creates cycle * }) * Graph.isAcyclic(cyclic) // => false * ``` * * @see {@link findCycle} for retrieving one cycle witness * @see {@link topo} for ordering a directed acyclic graph * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const isAcyclic: (graph: Graph | MutableGraph) => boolean; /** * Checks whether an undirected graph is bipartite. * * **When to use** * * Use when validating that nodes can be divided into two groups with every * edge crossing between the groups. * * **Details** * * A bipartite graph is one whose vertices can be divided into two disjoint sets * such that no two vertices within the same set are adjacent. * * **Example** (Checking bipartite graphs) * * ```ts import.meta.vitest * import { Graph } from "effect" * * // Bipartite graph (alternating coloring possible) * const bipartite = Graph.undirected((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * const d = Graph.addNode(mutable, "D") * Graph.addEdge(mutable, a, b, "edge") // Set 1: {A, C}, Set 2: {B, D} * Graph.addEdge(mutable, b, c, "edge") * Graph.addEdge(mutable, c, d, "edge") * }) * Graph.isBipartite(bipartite) // => true * * // Non-bipartite graph (odd cycle) * const triangle = Graph.undirected((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "edge") * Graph.addEdge(mutable, b, c, "edge") * Graph.addEdge(mutable, c, a, "edge") // Triangle (3-cycle) * }) * Graph.isBipartite(triangle) // => false * ``` * * @see {@link maximumBipartiteMatching} for matching nodes after validation * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const isBipartite: (graph: Graph | MutableGraph) => boolean; /** * A pair of matched nodes and the edge that realizes the match. * * **Details** * * `left` and `right` refer to the bipartition derived by * `maximumBipartiteMatching`, not to the stored edge orientation. * * @stability unstable * @category models * @since 4.0.0 */ export interface BipartiteMatch { readonly left: NodeIndex; readonly right: NodeIndex; readonly edge: EdgeIndex; } /** * Returns a maximum-cardinality matching of an undirected bipartite graph. * * **When to use** * * Use when assigning as many disjoint pairs as possible between the two sides * of a bipartite graph, such as workers to jobs or users to resources. * * **Details** * * The bipartition is derived internally. Self-loops and odd cycles throw a * `GraphError`. Isolated nodes are allowed. Parallel edges do not change the * matching cardinality, and the first edge in graph order between each matched * pair is reported. Results follow left-partition graph order. Hopcroft-Karp * runs in `O(E * sqrt(V))` time. * * **Gotchas** * * The graph must be undirected and bipartite. The derived left and right sides * are not based on stored edge orientation. * * **Example** (Matching a bipartite graph) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.undirected((mutable) => { * for (const node of ["A", "B", "X", "Y"]) Graph.addNode(mutable, node) * Graph.addEdge(mutable, 0, 2, "A-X") * Graph.addEdge(mutable, 0, 3, "A-Y") * Graph.addEdge(mutable, 1, 2, "B-X") * }) * * Graph.maximumBipartiteMatching(graph) // => [{ left: 0, right: 3, edge: 1 }, { left: 1, right: 2, edge: 2 }] * ``` * * @see {@link isBipartite} for validating the graph without computing a matching * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const maximumBipartiteMatching: (graph: Graph | MutableGraph) => Array; /** * Configuration for unweighted reachability queries. * * **When to use** * * Use when controlling whether reachability follows outgoing edges, incoming * edges, or either direction. * * **Details** * * `direction` defaults to `"outgoing"` and is ignored for undirected graphs. * * @stability unstable * @category configuration * @since 4.0.0 */ export interface ReachabilityConfig { readonly direction?: TraversalDirection; } /** * Returns minimum unweighted distances from a source to every reachable node. * * **When to use** * * Use when every edge represents one step and you need hop counts from one * source. * * **Details** * * Directed traversal is outgoing by default and can be changed with * `direction`. * * **Gotchas** * * Throws a `GraphError` when the source does not exist. * * @see {@link hasPath} when only a reachability boolean is needed * @see {@link bfs} for lazy traversal in increasing hop distance * @see {@link dijkstra} for weighted shortest paths * * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const unweightedDistances: { /** * Returns minimum unweighted distances from a source to every reachable node. * * **When to use** * * Use when every edge represents one step and you need hop counts from one * source. * * **Details** * * Directed traversal is outgoing by default and can be changed with * `direction`. * * **Gotchas** * * Throws a `GraphError` when the source does not exist. * * @see {@link hasPath} when only a reachability boolean is needed * @see {@link bfs} for lazy traversal in increasing hop distance * @see {@link dijkstra} for weighted shortest paths * * @stability unstable * @category algorithms * @since 4.0.0 */ (source: NodeIndex, options?: ReachabilityConfig): (graph: Graph | MutableGraph) => Map; /** * Returns minimum unweighted distances from a source to every reachable node. * * **When to use** * * Use when every edge represents one step and you need hop counts from one * source. * * **Details** * * Directed traversal is outgoing by default and can be changed with * `direction`. * * **Gotchas** * * Throws a `GraphError` when the source does not exist. * * @see {@link hasPath} when only a reachability boolean is needed * @see {@link bfs} for lazy traversal in increasing hop distance * @see {@link dijkstra} for weighted shortest paths * * @stability unstable * @category algorithms * @since 4.0.0 */ (graph: Graph | MutableGraph, source: NodeIndex, options?: ReachabilityConfig): Map; }; /** * Tests whether a target is reachable from a source. * * **When to use** * * Use when you only need a reachability boolean rather than distances or a * reconstructed path. * * **Details** * * Directed traversal is outgoing by default and can be changed with * `direction`. A node is reachable from itself. * * **Gotchas** * * Throws a `GraphError` when either endpoint does not exist. * * @see {@link unweightedDistances} for hop distances to all reachable nodes * @see {@link dijkstra} for a minimum-cost path * * @stability unstable * @category predicates * @since 4.0.0 */ export declare const hasPath: { /** * Tests whether a target is reachable from a source. * * **When to use** * * Use when you only need a reachability boolean rather than distances or a * reconstructed path. * * **Details** * * Directed traversal is outgoing by default and can be changed with * `direction`. A node is reachable from itself. * * **Gotchas** * * Throws a `GraphError` when either endpoint does not exist. * * @see {@link unweightedDistances} for hop distances to all reachable nodes * @see {@link dijkstra} for a minimum-cost path * * @stability unstable * @category predicates * @since 4.0.0 */ (source: NodeIndex, target: NodeIndex, options?: ReachabilityConfig): (graph: Graph | MutableGraph) => boolean; /** * Tests whether a target is reachable from a source. * * **When to use** * * Use when you only need a reachability boolean rather than distances or a * reconstructed path. * * **Details** * * Directed traversal is outgoing by default and can be changed with * `direction`. A node is reachable from itself. * * **Gotchas** * * Throws a `GraphError` when either endpoint does not exist. * * @see {@link unweightedDistances} for hop distances to all reachable nodes * @see {@link dijkstra} for a minimum-cost path * * @stability unstable * @category predicates * @since 4.0.0 */ (graph: Graph | MutableGraph, source: NodeIndex, target: NodeIndex, options?: ReachabilityConfig): boolean; }; /** * Returns the connected components of an undirected graph. * * **When to use** * * Use when partitioning an undirected graph into groups connected by paths. * * **Details** * * Each component is represented as an array of node indices. Isolated nodes * form singleton components. * * **Gotchas** * * Throws a `GraphError` when used with a directed graph. * * **Example** (Finding connected components) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.undirected((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * const d = Graph.addNode(mutable, "D") * Graph.addEdge(mutable, a, b, "edge") // Component 1: A-B * Graph.addEdge(mutable, c, d, "edge") // Component 2: C-D * }) * * Graph.connectedComponents(graph) // => [[0, 1], [2, 3]] * ``` * * @see {@link isConnected} when only a boolean connectivity check is needed * @see {@link weaklyConnectedComponents} for directed graphs with orientation ignored * @see {@link stronglyConnectedComponents} for mutual directed reachability * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const connectedComponents: (graph: Graph | MutableGraph) => Array>; /** * Returns the edges whose removal increases the number of connected components. * * **When to use** * * Use when locating single-edge failure points in an undirected network. * * **Details** * * Parent edges are tracked by edge index, so a parallel edge prevents either * edge from being a bridge. Self-loops are never bridges. Results follow graph * edge order. The iterative low-link traversal is stack-safe and runs in * `O(V + E)` time. * * **Gotchas** * * Throws a `GraphError` when used with a directed graph. * * **Example** (Finding bridge edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.undirected((mutable) => { * for (let i = 0; i < 3; i++) Graph.addNode(mutable, undefined) * Graph.addEdge(mutable, 0, 1, undefined) * Graph.addEdge(mutable, 1, 2, undefined) * }) * * Graph.bridges(graph) // => [0, 1] * ``` * * @see {@link articulationPoints} for single-node failure points * @see {@link biconnectedComponents} for maximal regions without an articulation split * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const bridges: (graph: Graph | MutableGraph) => Array; /** * Returns the nodes whose removal increases the number of connected components. * * **When to use** * * Use when locating single-node failure points in an undirected network. * * **Details** * * Disconnected components, parallel edges, and self-loops are handled by an * iterative, stack-safe low-link traversal in `O(V + E)` time. Results follow * graph node order. * * **Gotchas** * * Throws a `GraphError` when used with a directed graph. * * **Example** (Finding articulation points) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.undirected((mutable) => { * for (let i = 0; i < 3; i++) Graph.addNode(mutable, undefined) * Graph.addEdge(mutable, 0, 1, undefined) * Graph.addEdge(mutable, 1, 2, undefined) * }) * * Graph.articulationPoints(graph) // => [1] * ``` * * @see {@link bridges} for single-edge failure points * @see {@link biconnectedComponents} for the regions joined at articulation points * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const articulationPoints: (graph: Graph | MutableGraph) => Array; /** * Returns the maximal biconnected node components of an undirected graph. * * **When to use** * * Use when decomposing an undirected graph into maximal regions that remain * connected after removing any one node from the region. * * **Details** * * Articulation points can occur in more than one component. Isolated vertices * are excluded, while a vertex with a self-loop forms a singleton component. * Nodes within components and the components themselves follow graph order. * Parallel edges are treated independently. The iterative low-link traversal * is stack-safe and runs in `O(V + E)` time. * * **Gotchas** * * Throws a `GraphError` when used with a directed graph. * * **Example** (Finding biconnected components) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.undirected((mutable) => { * for (let i = 0; i < 5; i++) Graph.addNode(mutable, undefined) * Graph.addEdge(mutable, 0, 1, undefined) * Graph.addEdge(mutable, 1, 2, undefined) * Graph.addEdge(mutable, 2, 0, undefined) * Graph.addEdge(mutable, 2, 3, undefined) * Graph.addEdge(mutable, 3, 4, undefined) * Graph.addEdge(mutable, 4, 2, undefined) * }) * * Graph.biconnectedComponents(graph) // => [[0, 1, 2], [2, 3, 4]] * ``` * * @see {@link articulationPoints} for the nodes shared between components * @see {@link bridges} for edges whose removal disconnects the graph * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const biconnectedComponents: (graph: Graph | MutableGraph) => Array>; /** * Configuration for source-to-target flow algorithms. * * **When to use** * * Use when defining endpoints and edge capacities for `maximumFlow` or * `minimumCut`. * * **Details** * * `capacity` receives stored edge data and must return a finite, * non-negative number. * * **Gotchas** * * The source and target must be distinct existing nodes in a directed graph. * * @stability unstable * @category configuration * @since 4.0.0 */ export interface MaximumFlowConfig { readonly source: NodeIndex; readonly target: NodeIndex; readonly capacity: (edge: E) => number; } /** * Maximum flow value, per-edge flows, and a corresponding minimum cut. * * **Details** * * `flows` contains every original edge, including zero-flow edges. `cut` * contains the crossing edge identifiers of the corresponding minimum cut. * * @stability unstable * @category models * @since 4.0.0 */ export interface MaximumFlowResult { readonly value: number; readonly flows: Map; readonly cut: Array; } /** * Minimum cut value, crossing edges, and residual-reachability partitions. * * **Details** * * `source` contains nodes residual-reachable from the configured source and * `target` contains the remaining nodes. * * @stability unstable * @category models * @since 4.0.0 */ export interface MinimumCutResult { readonly value: number; readonly edges: Array; readonly source: Array; readonly target: Array; } /** * Returns a maximum flow and corresponding minimum cut for a directed graph. * * **When to use** * * Use when computing the greatest transferable capacity from one node to * another and per-edge flow values are required. * * **Details** * * Parallel edges retain independent capacities, self-loops carry no * source-to-target flow, and the flow map includes every original edge in graph * order, including zero-flow edges. Edmonds-Karp runs in `O(V * E^2)` time. * * **Gotchas** * * The graph must be directed. Capacities must be finite and non-negative. * Missing or equal endpoints, invalid capacities, and a total flow outside the * finite number range throw a `GraphError`. Self-loops always carry zero flow. * * **Example** (Computing maximum flow) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * for (const node of ["source", "a", "target"]) Graph.addNode(mutable, node) * Graph.addEdge(mutable, 0, 1, 3) * Graph.addEdge(mutable, 1, 2, 2) * Graph.addEdge(mutable, 0, 2, 1) * }) * * Graph.maximumFlow(graph, { source: 0, target: 2, capacity: (edge) => edge }).value // => 3 * ``` * * @see {@link minimumCut} for the residual-reachability partition * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const maximumFlow: { /** * Returns a maximum flow and corresponding minimum cut for a directed graph. * * **When to use** * * Use when computing the greatest transferable capacity from one node to * another and per-edge flow values are required. * * **Details** * * Parallel edges retain independent capacities, self-loops carry no * source-to-target flow, and the flow map includes every original edge in graph * order, including zero-flow edges. Edmonds-Karp runs in `O(V * E^2)` time. * * **Gotchas** * * The graph must be directed. Capacities must be finite and non-negative. * Missing or equal endpoints, invalid capacities, and a total flow outside the * finite number range throw a `GraphError`. Self-loops always carry zero flow. * * **Example** (Computing maximum flow) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * for (const node of ["source", "a", "target"]) Graph.addNode(mutable, node) * Graph.addEdge(mutable, 0, 1, 3) * Graph.addEdge(mutable, 1, 2, 2) * Graph.addEdge(mutable, 0, 2, 1) * }) * * Graph.maximumFlow(graph, { source: 0, target: 2, capacity: (edge) => edge }).value // => 3 * ``` * * @see {@link minimumCut} for the residual-reachability partition * @stability unstable * @category algorithms * @since 4.0.0 */ (config: MaximumFlowConfig): (graph: Graph | MutableGraph) => MaximumFlowResult; /** * Returns a maximum flow and corresponding minimum cut for a directed graph. * * **When to use** * * Use when computing the greatest transferable capacity from one node to * another and per-edge flow values are required. * * **Details** * * Parallel edges retain independent capacities, self-loops carry no * source-to-target flow, and the flow map includes every original edge in graph * order, including zero-flow edges. Edmonds-Karp runs in `O(V * E^2)` time. * * **Gotchas** * * The graph must be directed. Capacities must be finite and non-negative. * Missing or equal endpoints, invalid capacities, and a total flow outside the * finite number range throw a `GraphError`. Self-loops always carry zero flow. * * **Example** (Computing maximum flow) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * for (const node of ["source", "a", "target"]) Graph.addNode(mutable, node) * Graph.addEdge(mutable, 0, 1, 3) * Graph.addEdge(mutable, 1, 2, 2) * Graph.addEdge(mutable, 0, 2, 1) * }) * * Graph.maximumFlow(graph, { source: 0, target: 2, capacity: (edge) => edge }).value // => 3 * ``` * * @see {@link minimumCut} for the residual-reachability partition * @stability unstable * @category algorithms * @since 4.0.0 */ (graph: Graph | MutableGraph, config: MaximumFlowConfig): MaximumFlowResult; }; /** * Returns a minimum cut and its node partitions for a directed graph. * * **When to use** * * Use when identifying the minimum-capacity edges that separate a source from * a target, together with the resulting node partitions. * * **Details** * * The source partition contains nodes reachable from the source in the final * residual network; the target partition contains its complement. Both follow * graph node order. Cut edges follow graph edge order, and their total capacity * equals the returned maximum-flow value. Validation, parallel-edge, * self-loop, and `O(V * E^2)` complexity behavior match `maximumFlow`. * * **Gotchas** * * The graph must be directed. Invalid capacities, missing endpoints, or equal * source and target nodes throw a `GraphError`. * * **Example** (Partitioning a minimum cut) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * for (const node of ["source", "a", "target"]) Graph.addNode(mutable, node) * Graph.addEdge(mutable, 0, 1, 2) * Graph.addEdge(mutable, 1, 2, 1) * }) * * Graph.minimumCut(graph, { source: 0, target: 2, capacity: (edge) => edge }).source // => [0, 1] * ``` * * @see {@link maximumFlow} for per-edge flow values * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const minimumCut: { /** * Returns a minimum cut and its node partitions for a directed graph. * * **When to use** * * Use when identifying the minimum-capacity edges that separate a source from * a target, together with the resulting node partitions. * * **Details** * * The source partition contains nodes reachable from the source in the final * residual network; the target partition contains its complement. Both follow * graph node order. Cut edges follow graph edge order, and their total capacity * equals the returned maximum-flow value. Validation, parallel-edge, * self-loop, and `O(V * E^2)` complexity behavior match `maximumFlow`. * * **Gotchas** * * The graph must be directed. Invalid capacities, missing endpoints, or equal * source and target nodes throw a `GraphError`. * * **Example** (Partitioning a minimum cut) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * for (const node of ["source", "a", "target"]) Graph.addNode(mutable, node) * Graph.addEdge(mutable, 0, 1, 2) * Graph.addEdge(mutable, 1, 2, 1) * }) * * Graph.minimumCut(graph, { source: 0, target: 2, capacity: (edge) => edge }).source // => [0, 1] * ``` * * @see {@link maximumFlow} for per-edge flow values * @stability unstable * @category algorithms * @since 4.0.0 */ (config: MaximumFlowConfig): (graph: Graph | MutableGraph) => MinimumCutResult; /** * Returns a minimum cut and its node partitions for a directed graph. * * **When to use** * * Use when identifying the minimum-capacity edges that separate a source from * a target, together with the resulting node partitions. * * **Details** * * The source partition contains nodes reachable from the source in the final * residual network; the target partition contains its complement. Both follow * graph node order. Cut edges follow graph edge order, and their total capacity * equals the returned maximum-flow value. Validation, parallel-edge, * self-loop, and `O(V * E^2)` complexity behavior match `maximumFlow`. * * **Gotchas** * * The graph must be directed. Invalid capacities, missing endpoints, or equal * source and target nodes throw a `GraphError`. * * **Example** (Partitioning a minimum cut) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * for (const node of ["source", "a", "target"]) Graph.addNode(mutable, node) * Graph.addEdge(mutable, 0, 1, 2) * Graph.addEdge(mutable, 1, 2, 1) * }) * * Graph.minimumCut(graph, { source: 0, target: 2, capacity: (edge) => edge }).source // => [0, 1] * ``` * * @see {@link maximumFlow} for per-edge flow values * @stability unstable * @category algorithms * @since 4.0.0 */ (graph: Graph | MutableGraph, config: MaximumFlowConfig): MinimumCutResult; }; /** * Finds weakly connected components in a directed graph. * * **When to use** * * Use when grouping directed nodes by connectivity while ignoring edge * orientation. * * **Details** * * Edge direction is ignored while partitioning nodes. Isolated nodes form * singleton components. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. * * @see {@link isWeaklyConnected} when only a boolean check is needed * @see {@link stronglyConnectedComponents} for mutual directed reachability * * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const weaklyConnectedComponents: (graph: Graph | MutableGraph) => Array>; /** * Returns the strongly connected components of a directed graph. * * **When to use** * * Use when grouping nodes so every node in a component can reach every other * node in that component. * * **Details** * * Each component is represented as an array of node indices and is computed * with Kosaraju's algorithm. * * **Gotchas** * * Throws a `GraphError` when used with an undirected graph. * * **Example** (Finding strongly connected components) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, "A->B") * Graph.addEdge(mutable, b, c, "B->C") * Graph.addEdge(mutable, c, a, "C->A") // Creates SCC: A-B-C * }) * * Graph.stronglyConnectedComponents(graph) // => [[0, 2, 1]] * ``` * * @see {@link isStronglyConnected} when only a boolean check is needed * @see {@link weaklyConnectedComponents} when edge orientation should be ignored * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const stronglyConnectedComponents: (graph: Graph | MutableGraph) => Array>; /** * Tests whether an undirected graph has at most one connected component. * * **When to use** * * Use when checking undirected connectivity without allocating the component * partition. * * **Gotchas** * * The empty graph is considered connected. Throws a `GraphError` when used * with a directed graph. * * @see {@link connectedComponents} for the component partition * * @stability unstable * @category predicates * @since 4.0.0 */ export declare const isConnected: (graph: Graph | MutableGraph) => boolean; /** * Tests whether a directed graph has at most one weakly connected component. * * **When to use** * * Use when checking whether a directed graph is connected after ignoring edge * orientation. * * **Gotchas** * * The empty graph is considered weakly connected. Throws a `GraphError` when * used with an undirected graph. * * @see {@link isStronglyConnected} when edge orientation must be respected * * @stability unstable * @category predicates * @since 4.0.0 */ export declare const isWeaklyConnected: (graph: Graph | MutableGraph) => boolean; /** * Tests whether a directed graph has at most one strongly connected component. * * **When to use** * * Use when checking that every node in a directed graph can reach every other * node. * * **Gotchas** * * The empty graph is considered strongly connected. Throws a `GraphError` when * used with an undirected graph. * * @see {@link isWeaklyConnected} when edge orientation should be ignored * * @stability unstable * @category predicates * @since 4.0.0 */ export declare const isStronglyConnected: (graph: Graph | MutableGraph) => boolean; /** * Tests whether a non-empty undirected graph is a tree. * * **When to use** * * Use when validating that an undirected graph is connected and has no cycle. * * **Gotchas** * * The empty graph is not a tree. Parallel edges and self-loops prevent a graph * from being a tree. Throws a `GraphError` when used with a directed graph. * * @stability unstable * @category predicates * @since 4.0.0 */ export declare const isTree: (graph: Graph | MutableGraph) => boolean; /** * Returns a minimum spanning forest of an undirected graph using Kruskal's * algorithm. * * **When to use** * * Use when selecting a minimum-cost acyclic connector for every connected * component of an undirected graph. * * **Details** * * All node indices and selected edge indices are preserved. Negative finite * weights are allowed, `Infinity` marks an unavailable edge, and equal weights * are resolved by original edge order. Disconnected inputs produce a forest, * and isolated nodes remain present. * * **Gotchas** * * Throws a `GraphError` for a directed graph or when a weight is `NaN` or * `-Infinity`. Edges weighted `Infinity` are omitted. * * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const minimumSpanningForest: { /** * Returns a minimum spanning forest of an undirected graph using Kruskal's * algorithm. * * **When to use** * * Use when selecting a minimum-cost acyclic connector for every connected * component of an undirected graph. * * **Details** * * All node indices and selected edge indices are preserved. Negative finite * weights are allowed, `Infinity` marks an unavailable edge, and equal weights * are resolved by original edge order. Disconnected inputs produce a forest, * and isolated nodes remain present. * * **Gotchas** * * Throws a `GraphError` for a directed graph or when a weight is `NaN` or * `-Infinity`. Edges weighted `Infinity` are omitted. * * @stability unstable * @category algorithms * @since 4.0.0 */ (cost: (edgeData: E) => number): (graph: Graph | MutableGraph) => Graph; /** * Returns a minimum spanning forest of an undirected graph using Kruskal's * algorithm. * * **When to use** * * Use when selecting a minimum-cost acyclic connector for every connected * component of an undirected graph. * * **Details** * * All node indices and selected edge indices are preserved. Negative finite * weights are allowed, `Infinity` marks an unavailable edge, and equal weights * are resolved by original edge order. Disconnected inputs produce a forest, * and isolated nodes remain present. * * **Gotchas** * * Throws a `GraphError` for a directed graph or when a weight is `NaN` or * `-Infinity`. Edges weighted `Infinity` are omitted. * * @stability unstable * @category algorithms * @since 4.0.0 */ (graph: Graph | MutableGraph, cost: (edgeData: E) => number): Graph; }; /** * Returns the transitive reduction of a directed acyclic graph. * * **When to use** * * Use when simplifying a dependency DAG while preserving which nodes can * reach which other nodes. * * **Details** * * The result preserves reachability with the fewest structural source-target * pairs. Node and retained edge indices are preserved. * * **Gotchas** * * This operation is structural and ignores edge costs. Parallel edges are * coalesced by retaining the first edge for each required pair. Throws a * `GraphError` for an undirected graph or cyclic input. * * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const transitiveReduction: (graph: Graph | MutableGraph) => Graph; /** * Result of a shortest path computation. * * **When to use** * * Use to read the successful source-to-target shortest path returned by * path-finding algorithms, including the ordered node and edge indices, total * distance, and traversed edge data. * * **Details** * * Contains the node-index path, the traversed edge indices, the total numeric * distance, and the edge data encountered along the path. * * **Gotchas** * * `costs` contains original edge data, not the numeric output of the cost * function unless the edge data is numeric. * * @stability unstable * @category models * @since 3.18.0 */ export interface PathResult { readonly path: Array; readonly edges: Array; readonly distance: number; readonly costs: Array; } /** * Configuration for finding a shortest path with Dijkstra's algorithm. * * **When to use** * * Use when configuring `dijkstra` to find a shortest path between two existing * node indices with non-negative edge costs. * * **Details** * * Specifies the source and target node indices, plus a cost function that maps * each edge's data to a non-negative numeric weight. `Infinity` is allowed and * behaves like an impassable edge. * * **Gotchas** * * `dijkstra` throws a `GraphError` when either endpoint does not exist or when * the cost function returns a negative weight or `NaN`. * * @stability unstable * @category configuration * @since 3.18.0 */ export interface DijkstraConfig { source: NodeIndex; target: NodeIndex; cost: (edgeData: E) => number; } /** * Finds the shortest path from the configured source node to the target node * using Dijkstra's algorithm. * * **When to use** * * Use when you need one source-to-target shortest path and every edge cost is * non-negative. * * **Details** * * Edge costs must be non-negative and not `NaN`. `Infinity` is allowed and * behaves like an impassable edge. Returns `Option.none()` when the target is * not reachable. * * **Gotchas** * * Throws a `GraphError` when either endpoint is missing or an edge cost is * negative or `NaN`, or when a path distance exceeds the finite number range. * * **Example** (Finding shortest paths with Dijkstra) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 5) * Graph.addEdge(mutable, a, c, 10) * Graph.addEdge(mutable, b, c, 2) * }) * * const result = Graph.dijkstra(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([7, [0, 1, 2]]) * ``` * * @see {@link astar} when a useful heuristic can guide the search * @see {@link bellmanFord} when edge costs may be negative * @see {@link floydWarshall} when shortest paths are needed for all pairs * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const dijkstra: { /** * Finds the shortest path from the configured source node to the target node * using Dijkstra's algorithm. * * **When to use** * * Use when you need one source-to-target shortest path and every edge cost is * non-negative. * * **Details** * * Edge costs must be non-negative and not `NaN`. `Infinity` is allowed and * behaves like an impassable edge. Returns `Option.none()` when the target is * not reachable. * * **Gotchas** * * Throws a `GraphError` when either endpoint is missing or an edge cost is * negative or `NaN`, or when a path distance exceeds the finite number range. * * **Example** (Finding shortest paths with Dijkstra) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 5) * Graph.addEdge(mutable, a, c, 10) * Graph.addEdge(mutable, b, c, 2) * }) * * const result = Graph.dijkstra(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([7, [0, 1, 2]]) * ``` * * @see {@link astar} when a useful heuristic can guide the search * @see {@link bellmanFord} when edge costs may be negative * @see {@link floydWarshall} when shortest paths are needed for all pairs * @stability unstable * @category algorithms * @since 3.18.0 */ (config: DijkstraConfig): (graph: Graph | MutableGraph) => Option.Option>; /** * Finds the shortest path from the configured source node to the target node * using Dijkstra's algorithm. * * **When to use** * * Use when you need one source-to-target shortest path and every edge cost is * non-negative. * * **Details** * * Edge costs must be non-negative and not `NaN`. `Infinity` is allowed and * behaves like an impassable edge. Returns `Option.none()` when the target is * not reachable. * * **Gotchas** * * Throws a `GraphError` when either endpoint is missing or an edge cost is * negative or `NaN`, or when a path distance exceeds the finite number range. * * **Example** (Finding shortest paths with Dijkstra) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 5) * Graph.addEdge(mutable, a, c, 10) * Graph.addEdge(mutable, b, c, 2) * }) * * const result = Graph.dijkstra(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([7, [0, 1, 2]]) * ``` * * @see {@link astar} when a useful heuristic can guide the search * @see {@link bellmanFord} when edge costs may be negative * @see {@link floydWarshall} when shortest paths are needed for all pairs * @stability unstable * @category algorithms * @since 3.18.0 */ (graph: Graph | MutableGraph, config: DijkstraConfig): Option.Option>; }; /** * Result of an all-pairs shortest path computation. * * **When to use** * * Use when storing or passing around the complete output of `floydWarshall` so * callers can look up shortest distances, node and edge paths, and edge data * for any source and target node pair. * * **Details** * * Contains distance, node-path, edge-index-path, and edge-data maps keyed by * source and target node indices. Unreachable pairs have distance `Infinity`, * path `null`, and empty edge and cost arrays. * * @stability unstable * @category models * @since 3.18.0 */ export interface AllPairsResult { readonly distances: Map>; readonly paths: Map | null>>; readonly edges: Map>>; readonly costs: Map>>; } /** * Finds shortest paths between all pairs of nodes using the Floyd-Warshall * algorithm. * * **When to use** * * Use when many or all node pairs will be queried and cubic distance computation * plus storage for reconstructed paths is acceptable. * * **Details** * * Computes distances, reconstructed node paths, and edge-data paths for every * source and target pair. Distance computation takes O(V^3) time. Negative edge * weights are allowed, and `Infinity` behaves like an impassable edge. Immutable * path witnesses can require O(V^3) working storage; reconstructed paths have * repeated nodes removed. * * **Gotchas** * * A `GraphError` is thrown if any edge weight is `NaN` or `-Infinity`, or if * finite arithmetic overflows or underflows, or if any negative cycle is * detected. * * **Example** (Finding all-pairs shortest paths) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 3) * Graph.addEdge(mutable, b, c, 2) * Graph.addEdge(mutable, a, c, 7) * }) * * const result = Graph.floydWarshall(graph, (edgeData) => edgeData) * const shortest = { distance: result.distances.get(0)?.get(2), path: result.paths.get(0)?.get(2) } * shortest // => { distance: 5, path: [0, 1, 2] } * ``` * * @see {@link dijkstra} for one query with non-negative edge costs * @see {@link bellmanFord} for one query that may include negative edge costs * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const floydWarshall: { /** * Finds shortest paths between all pairs of nodes using the Floyd-Warshall * algorithm. * * **When to use** * * Use when many or all node pairs will be queried and cubic distance computation * plus storage for reconstructed paths is acceptable. * * **Details** * * Computes distances, reconstructed node paths, and edge-data paths for every * source and target pair. Distance computation takes O(V^3) time. Negative edge * weights are allowed, and `Infinity` behaves like an impassable edge. Immutable * path witnesses can require O(V^3) working storage; reconstructed paths have * repeated nodes removed. * * **Gotchas** * * A `GraphError` is thrown if any edge weight is `NaN` or `-Infinity`, or if * finite arithmetic overflows or underflows, or if any negative cycle is * detected. * * **Example** (Finding all-pairs shortest paths) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 3) * Graph.addEdge(mutable, b, c, 2) * Graph.addEdge(mutable, a, c, 7) * }) * * const result = Graph.floydWarshall(graph, (edgeData) => edgeData) * const shortest = { distance: result.distances.get(0)?.get(2), path: result.paths.get(0)?.get(2) } * shortest // => { distance: 5, path: [0, 1, 2] } * ``` * * @see {@link dijkstra} for one query with non-negative edge costs * @see {@link bellmanFord} for one query that may include negative edge costs * @stability unstable * @category algorithms * @since 3.18.0 */ (cost: (edgeData: E) => number): (graph: Graph | MutableGraph) => AllPairsResult; /** * Finds shortest paths between all pairs of nodes using the Floyd-Warshall * algorithm. * * **When to use** * * Use when many or all node pairs will be queried and cubic distance computation * plus storage for reconstructed paths is acceptable. * * **Details** * * Computes distances, reconstructed node paths, and edge-data paths for every * source and target pair. Distance computation takes O(V^3) time. Negative edge * weights are allowed, and `Infinity` behaves like an impassable edge. Immutable * path witnesses can require O(V^3) working storage; reconstructed paths have * repeated nodes removed. * * **Gotchas** * * A `GraphError` is thrown if any edge weight is `NaN` or `-Infinity`, or if * finite arithmetic overflows or underflows, or if any negative cycle is * detected. * * **Example** (Finding all-pairs shortest paths) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 3) * Graph.addEdge(mutable, b, c, 2) * Graph.addEdge(mutable, a, c, 7) * }) * * const result = Graph.floydWarshall(graph, (edgeData) => edgeData) * const shortest = { distance: result.distances.get(0)?.get(2), path: result.paths.get(0)?.get(2) } * shortest // => { distance: 5, path: [0, 1, 2] } * ``` * * @see {@link dijkstra} for one query with non-negative edge costs * @see {@link bellmanFord} for one query that may include negative edge costs * @stability unstable * @category algorithms * @since 3.18.0 */ (graph: Graph | MutableGraph, cost: (edgeData: E) => number): AllPairsResult; }; /** * Configuration for finding a shortest path with the A* algorithm. * * **When to use** * * Use when configuring `astar` for point-to-point shortest-path searches where * node data can provide a heuristic estimate toward the target. * * **Details** * * Specifies the source and target node indices, an edge-cost function that maps * edge data to non-negative weights, and a heuristic that estimates the * remaining cost from a node to the target. * * **Gotchas** * * Heuristic values must be finite and the heuristic must be consistent for A* * to guarantee a shortest path. * * @stability unstable * @category configuration * @since 3.18.0 */ export interface AstarConfig { source: NodeIndex; target: NodeIndex; cost: (edgeData: E) => number; heuristic: (sourceNodeData: N, targetNodeData: N) => number; } /** * Finds the shortest path from the configured source node to the target node * using the A* pathfinding algorithm. * * **When to use** * * Use when a meaningful heuristic can reduce point-to-point search compared * with Dijkstra's algorithm. * * **Details** * * The edge-cost function must return non-negative weights and not `NaN`. * `Infinity` is allowed and behaves like an impassable edge. Returns * `Option.none()` when the target is not reachable. * * **Gotchas** * * The heuristic must be consistent for the shortest-path guarantee and must * return finite values. Missing endpoints, invalid edge costs, or non-finite * heuristic values or arithmetic results throw a `GraphError`. * * **Example** (Finding shortest paths with A*) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed<{ x: number; y: number }, number>((mutable) => { * const a = Graph.addNode(mutable, { x: 0, y: 0 }) * const b = Graph.addNode(mutable, { x: 1, y: 0 }) * const c = Graph.addNode(mutable, { x: 2, y: 0 }) * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Manhattan distance heuristic * const heuristic = ( * nodeData: { x: number; y: number }, * targetData: { x: number; y: number } * ) => Math.abs(nodeData.x - targetData.x) + Math.abs(nodeData.y - targetData.y) * * const result = Graph.astar(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData, * heuristic * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([2, [0, 1, 2]]) * ``` * * @see {@link dijkstra} when no useful heuristic is available * @see {@link bellmanFord} when edge costs may be negative * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const astar: { /** * Finds the shortest path from the configured source node to the target node * using the A* pathfinding algorithm. * * **When to use** * * Use when a meaningful heuristic can reduce point-to-point search compared * with Dijkstra's algorithm. * * **Details** * * The edge-cost function must return non-negative weights and not `NaN`. * `Infinity` is allowed and behaves like an impassable edge. Returns * `Option.none()` when the target is not reachable. * * **Gotchas** * * The heuristic must be consistent for the shortest-path guarantee and must * return finite values. Missing endpoints, invalid edge costs, or non-finite * heuristic values or arithmetic results throw a `GraphError`. * * **Example** (Finding shortest paths with A*) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed<{ x: number; y: number }, number>((mutable) => { * const a = Graph.addNode(mutable, { x: 0, y: 0 }) * const b = Graph.addNode(mutable, { x: 1, y: 0 }) * const c = Graph.addNode(mutable, { x: 2, y: 0 }) * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Manhattan distance heuristic * const heuristic = ( * nodeData: { x: number; y: number }, * targetData: { x: number; y: number } * ) => Math.abs(nodeData.x - targetData.x) + Math.abs(nodeData.y - targetData.y) * * const result = Graph.astar(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData, * heuristic * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([2, [0, 1, 2]]) * ``` * * @see {@link dijkstra} when no useful heuristic is available * @see {@link bellmanFord} when edge costs may be negative * @stability unstable * @category algorithms * @since 3.18.0 */ (config: AstarConfig): (graph: Graph | MutableGraph) => Option.Option>; /** * Finds the shortest path from the configured source node to the target node * using the A* pathfinding algorithm. * * **When to use** * * Use when a meaningful heuristic can reduce point-to-point search compared * with Dijkstra's algorithm. * * **Details** * * The edge-cost function must return non-negative weights and not `NaN`. * `Infinity` is allowed and behaves like an impassable edge. Returns * `Option.none()` when the target is not reachable. * * **Gotchas** * * The heuristic must be consistent for the shortest-path guarantee and must * return finite values. Missing endpoints, invalid edge costs, or non-finite * heuristic values or arithmetic results throw a `GraphError`. * * **Example** (Finding shortest paths with A*) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed<{ x: number; y: number }, number>((mutable) => { * const a = Graph.addNode(mutable, { x: 0, y: 0 }) * const b = Graph.addNode(mutable, { x: 1, y: 0 }) * const c = Graph.addNode(mutable, { x: 2, y: 0 }) * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Manhattan distance heuristic * const heuristic = ( * nodeData: { x: number; y: number }, * targetData: { x: number; y: number } * ) => Math.abs(nodeData.x - targetData.x) + Math.abs(nodeData.y - targetData.y) * * const result = Graph.astar(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData, * heuristic * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([2, [0, 1, 2]]) * ``` * * @see {@link dijkstra} when no useful heuristic is available * @see {@link bellmanFord} when edge costs may be negative * @stability unstable * @category algorithms * @since 3.18.0 */ (graph: Graph | MutableGraph, config: AstarConfig): Option.Option>; }; /** * Configuration for finding a shortest path with the Bellman-Ford algorithm. * * **When to use** * * Use when configuring `bellmanFord` to find a shortest path where edge * weights may be negative. * * **Details** * * Specifies the source and target node indices, plus a cost function that maps * each edge's data to a numeric weight. * * @stability unstable * @category configuration * @since 3.18.0 */ export interface BellmanFordConfig { source: NodeIndex; target: NodeIndex; cost: (edgeData: E) => number; } /** * Finds the shortest path from the configured source node to the target node * using the Bellman-Ford algorithm. * * **When to use** * * Use when one source-to-target shortest-path query may traverse negative-cost * edges. * * **Details** * * Negative edge weights are allowed, and `Infinity` behaves like an impassable * edge. Returns `Option.none()` when the target is unreachable. A reachable * negative cycle only causes failure when it can affect the target. * * **Gotchas** * * Missing endpoints, unsupported weights, finite-range overflow, or a relevant * negative cycle throw a `GraphError`. In an undirected graph, any reachable * negative edge forms a negative cycle because it can be traversed both ways. * * **Example** (Finding shortest paths with Bellman-Ford) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, -1) // Negative weight allowed * Graph.addEdge(mutable, b, c, 3) * Graph.addEdge(mutable, a, c, 5) * }) * * const result = Graph.bellmanFord(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([2, [0, 1, 2]]) * ``` * * @see {@link dijkstra} for non-negative edge costs * @stability unstable * @category algorithms * @since 3.18.0 */ export declare const bellmanFord: { /** * Finds the shortest path from the configured source node to the target node * using the Bellman-Ford algorithm. * * **When to use** * * Use when one source-to-target shortest-path query may traverse negative-cost * edges. * * **Details** * * Negative edge weights are allowed, and `Infinity` behaves like an impassable * edge. Returns `Option.none()` when the target is unreachable. A reachable * negative cycle only causes failure when it can affect the target. * * **Gotchas** * * Missing endpoints, unsupported weights, finite-range overflow, or a relevant * negative cycle throw a `GraphError`. In an undirected graph, any reachable * negative edge forms a negative cycle because it can be traversed both ways. * * **Example** (Finding shortest paths with Bellman-Ford) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, -1) // Negative weight allowed * Graph.addEdge(mutable, b, c, 3) * Graph.addEdge(mutable, a, c, 5) * }) * * const result = Graph.bellmanFord(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([2, [0, 1, 2]]) * ``` * * @see {@link dijkstra} for non-negative edge costs * @stability unstable * @category algorithms * @since 3.18.0 */ (config: BellmanFordConfig): (graph: Graph | MutableGraph) => Option.Option>; /** * Finds the shortest path from the configured source node to the target node * using the Bellman-Ford algorithm. * * **When to use** * * Use when one source-to-target shortest-path query may traverse negative-cost * edges. * * **Details** * * Negative edge weights are allowed, and `Infinity` behaves like an impassable * edge. Returns `Option.none()` when the target is unreachable. A reachable * negative cycle only causes failure when it can affect the target. * * **Gotchas** * * Missing endpoints, unsupported weights, finite-range overflow, or a relevant * negative cycle throw a `GraphError`. In an undirected graph, any reachable * negative edge forms a negative cycle because it can be traversed both ways. * * **Example** (Finding shortest paths with Bellman-Ford) * * ```ts import.meta.vitest * import { Graph, Option } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, -1) // Negative weight allowed * Graph.addEdge(mutable, b, c, 3) * Graph.addEdge(mutable, a, c, 5) * }) * * const result = Graph.bellmanFord(graph, { * source: 0, * target: 2, * cost: (edgeData) => edgeData * }) * * Option.map(result, ({ distance, path }) => [distance, path] as const) // => Option.some([2, [0, 1, 2]]) * ``` * * @see {@link dijkstra} for non-negative edge costs * @stability unstable * @category algorithms * @since 3.18.0 */ (graph: Graph | MutableGraph, config: BellmanFordConfig): Option.Option>; }; /** * A repeatable lazy iterable of edge-aware graph paths. * * **When to use** * * Use as the lazy result of graph path-enumeration functions. * * **Details** * * Each fresh iterator repeats the path enumeration. * * @stability unstable * @category models * @since 4.0.0 */ export interface PathWalker extends Iterable> { } /** * Configuration for lazy simple-path enumeration. * * **When to use** * * Use when bounding enumeration of loop-free routes between two nodes. * * **Details** * * `limit` bounds the number of yielded paths and defaults to `Infinity`. * * **Gotchas** * * `limit` must be a non-negative integer or `Infinity`. * * @stability unstable * @category configuration * @since 4.0.0 */ export interface SimplePathsConfig { readonly source: NodeIndex; readonly target: NodeIndex; readonly limit?: number; } /** * Configuration for enumerating all tied shortest paths. * * **When to use** * * Use when bounding enumeration of every route tied for minimum total cost. * * **Details** * * Edge costs must be non-negative. `limit` bounds the number of yielded paths * and defaults to `Infinity`. * * **Gotchas** * * Invalid costs and limits throw a `GraphError` when evaluated. * * @stability unstable * @category configuration * @since 4.0.0 */ export interface AllShortestPathsConfig extends DijkstraConfig { readonly limit?: number; } /** * Lazily enumerates simple source-to-target paths in depth-first edge order. * * **When to use** * * Use when you need possible loop-free routes rather than only an optimal * route. * * **Details** * * Nodes are never repeated within a path, so enumeration is finite even for * cyclic graphs. Path distance is the number of traversed edges. * * **Gotchas** * * The number of simple paths can be exponential. Missing endpoints or an * invalid `limit` throw a `GraphError`. Mutable graphs are snapshotted when * iteration begins. * * @see {@link allShortestPaths} for enumerating only minimum-cost routes * * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const simplePaths: { /** * Lazily enumerates simple source-to-target paths in depth-first edge order. * * **When to use** * * Use when you need possible loop-free routes rather than only an optimal * route. * * **Details** * * Nodes are never repeated within a path, so enumeration is finite even for * cyclic graphs. Path distance is the number of traversed edges. * * **Gotchas** * * The number of simple paths can be exponential. Missing endpoints or an * invalid `limit` throw a `GraphError`. Mutable graphs are snapshotted when * iteration begins. * * @see {@link allShortestPaths} for enumerating only minimum-cost routes * * @stability unstable * @category algorithms * @since 4.0.0 */ (config: SimplePathsConfig): (graph: Graph | MutableGraph) => PathWalker; /** * Lazily enumerates simple source-to-target paths in depth-first edge order. * * **When to use** * * Use when you need possible loop-free routes rather than only an optimal * route. * * **Details** * * Nodes are never repeated within a path, so enumeration is finite even for * cyclic graphs. Path distance is the number of traversed edges. * * **Gotchas** * * The number of simple paths can be exponential. Missing endpoints or an * invalid `limit` throw a `GraphError`. Mutable graphs are snapshotted when * iteration begins. * * @see {@link allShortestPaths} for enumerating only minimum-cost routes * * @stability unstable * @category algorithms * @since 4.0.0 */ (graph: Graph | MutableGraph, config: SimplePathsConfig): PathWalker; }; /** * Lazily enumerates all simple paths tied for minimum total cost. * * **When to use** * * Use when every distinct route tied for the minimum total cost is required. * * **Details** * * Parallel edges produce distinct paths. Edge costs must be non-negative; * `Infinity` behaves as unavailable. * * **Gotchas** * * The number of tied paths can still be large. Missing endpoints, invalid * costs, arithmetic overflow, or an invalid `limit` throw a `GraphError`. * Mutable graphs are snapshotted when iteration begins. * * @see {@link dijkstra} when one shortest path is sufficient * @see {@link simplePaths} for routes regardless of cost * * @stability unstable * @category algorithms * @since 4.0.0 */ export declare const allShortestPaths: { /** * Lazily enumerates all simple paths tied for minimum total cost. * * **When to use** * * Use when every distinct route tied for the minimum total cost is required. * * **Details** * * Parallel edges produce distinct paths. Edge costs must be non-negative; * `Infinity` behaves as unavailable. * * **Gotchas** * * The number of tied paths can still be large. Missing endpoints, invalid * costs, arithmetic overflow, or an invalid `limit` throw a `GraphError`. * Mutable graphs are snapshotted when iteration begins. * * @see {@link dijkstra} when one shortest path is sufficient * @see {@link simplePaths} for routes regardless of cost * * @stability unstable * @category algorithms * @since 4.0.0 */ (config: AllShortestPathsConfig): (graph: Graph | MutableGraph) => PathWalker; /** * Lazily enumerates all simple paths tied for minimum total cost. * * **When to use** * * Use when every distinct route tied for the minimum total cost is required. * * **Details** * * Parallel edges produce distinct paths. Edge costs must be non-negative; * `Infinity` behaves as unavailable. * * **Gotchas** * * The number of tied paths can still be large. Missing endpoints, invalid * costs, arithmetic overflow, or an invalid `limit` throw a `GraphError`. * Mutable graphs are snapshotted when iteration begins. * * @see {@link dijkstra} when one shortest path is sufficient * @see {@link simplePaths} for routes regardless of cost * * @stability unstable * @category algorithms * @since 4.0.0 */ (graph: Graph | MutableGraph, config: AllShortestPathsConfig): PathWalker; }; /** * Represents an iterable wrapper used by graph traversal and listing APIs. * * **Details** * * A `Walker` yields `[index, data]` pairs lazily and can be viewed as just the * indices, just the values, or mapped entries with `indices`, `values`, * `entries`, and `visit`. * * **Example** (Working with node walkers) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, 1) * }) * * // Both traversal and element iterators return NodeWalker * const dfsNodes: Graph.NodeWalker = Graph.dfs(graph, { start: [0] }) * const allNodes: Graph.NodeWalker = Graph.nodes(graph) * * // Common interface for working with node iterables * function processNodes(nodeIterable: Graph.NodeWalker): Array { * return Array.from(Graph.indices(nodeIterable)) * } * * // Access node data using values() or entries() * Array.from(Graph.values(dfsNodes)) // => ["A", "B"] * Array.from(Graph.entries(allNodes)) // => [[0, "A"], [1, "B"]] * ``` * * @stability unstable * @category models * @since 3.18.0 */ export declare class Walker implements Iterable<[T, N]> { readonly [Symbol.iterator]: () => Iterator<[T, N]>; /** * Lazily maps each walker entry with the provided function. * * **Details** * * The function receives the index and data and runs as the returned iterable * is consumed. * * **Example** (Visiting walker elements) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, 1) * }) * * const dfs = Graph.dfs(graph, { start: [0] }) * * // Map to just the node data * Array.from(dfs.visit((index, data) => data)) // => ["A", "B"] * * // Map to custom objects * Array.from(dfs.visit((index, data) => ({ id: index, name: data }))) // => [{ id: 0, name: "A" }, { id: 1, name: "B" }] * ``` * * @since 4.0.0 */ readonly visit: (f: (index: T, data: N) => U) => Iterable; constructor(visit: (f: (index: T, data: N) => U) => Iterable); } /** * Type alias for node iteration using Walker. * NodeWalker is represented as Walker. * * **When to use** * * Use as the shared node walker type returned by graph traversal and node * listing APIs. * * @see {@link Walker} for the generic lazy iterator wrapper * @see {@link EdgeWalker} for edge iterators * * @stability unstable * @category models * @since 3.18.0 */ export type NodeWalker = Walker; /** * Type alias for edge iteration using Walker. * EdgeWalker is represented as Walker>. * * **When to use** * * Use to type helpers or parameters that consume edge iterators returned by * `Graph` APIs, where each item is keyed by an `EdgeIndex` and carries the * full `Edge`. * * @see {@link Walker} for the generic lazy iterator wrapper * @see {@link NodeWalker} for node iterators * @see {@link edges} for creating edge walkers * * @stability unstable * @category models * @since 3.18.0 */ export type EdgeWalker = Walker>; /** * Returns an iterator over the indices in the walker. * * **Example** (Iterating walker indices) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, 1) * }) * * const dfs = Graph.dfs(graph, { start: [0] }) * Array.from(Graph.indices(dfs)) // => [0, 1] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ export declare const indices: (walker: Walker) => Iterable; /** * Returns an iterator over the values (data) in the walker. * * **Example** (Iterating walker values) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, 1) * }) * * const dfs = Graph.dfs(graph, { start: [0] }) * Array.from(Graph.values(dfs)) // => ["A", "B"] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ export declare const values: (walker: Walker) => Iterable; /** * Returns an iterator over [index, data] entries in the walker. * * **Example** (Iterating walker entries) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * Graph.addEdge(mutable, a, b, 1) * }) * * const dfs = Graph.dfs(graph, { start: [0] }) * Array.from(Graph.entries(dfs)) // => [[0, "A"], [1, "B"]] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ export declare const entries: (walker: Walker) => Iterable<[T, N]>; /** * Configuration for DFS, BFS, and postorder graph traversals. * * **When to use** * * Use to configure the starting node indices and edge-following direction for * lazy graph traversals. * * **Details** * * `start` supplies the node indices where traversal begins. If it is omitted, * the iterator is empty. Distinct starts are prioritized in supplied order and * duplicates are ignored. `direction` chooses whether traversal follows outgoing * edges, incoming edges, or ignores edge direction. `radius` limits traversal * by edge distance from the nearest start node and accepts non-negative integers * or `Infinity`; omitting it means unbounded traversal. * * **Gotchas** * * Traversal creation validates and copies `start`, and throws a `GraphError` * when a start node does not exist or `radius` is invalid. Each fresh iterator * revalidates those starts against the graph snapshot it captures. Later * mutations are not observed by an active iterator. * * @stability unstable * @category configuration * @since 3.18.0 */ export interface SearchConfig { readonly start?: Array; readonly direction?: TraversalDirection; readonly radius?: number; } /** * Creates a lazy depth-first traversal iterator from the configured start * nodes. * * **When to use** * * Use when exploring one branch deeply before visiting sibling branches. * * **Details** * * If no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * * **Gotchas** * * An invalid radius or missing start node throws a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing depth-first) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Start from a specific node * Array.from(Graph.indices(Graph.dfs(graph, { start: [0] }))) // => [0, 1, 2] * * Array.from(Graph.indices(Graph.dfs(graph))) // => [] * ``` * * @see {@link bfs} for traversal in increasing hop distance * @see {@link dfsPostOrder} for emitting descendants before ancestors * @stability unstable * @category iterators * @since 3.18.0 */ export declare const dfs: { /** * Creates a lazy depth-first traversal iterator from the configured start * nodes. * * **When to use** * * Use when exploring one branch deeply before visiting sibling branches. * * **Details** * * If no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * * **Gotchas** * * An invalid radius or missing start node throws a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing depth-first) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Start from a specific node * Array.from(Graph.indices(Graph.dfs(graph, { start: [0] }))) // => [0, 1, 2] * * Array.from(Graph.indices(Graph.dfs(graph))) // => [] * ``` * * @see {@link bfs} for traversal in increasing hop distance * @see {@link dfsPostOrder} for emitting descendants before ancestors * @stability unstable * @category iterators * @since 3.18.0 */ (config?: SearchConfig): (graph: Graph | MutableGraph) => NodeWalker; /** * Creates a lazy depth-first traversal iterator from the configured start * nodes. * * **When to use** * * Use when exploring one branch deeply before visiting sibling branches. * * **Details** * * If no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * * **Gotchas** * * An invalid radius or missing start node throws a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing depth-first) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Start from a specific node * Array.from(Graph.indices(Graph.dfs(graph, { start: [0] }))) // => [0, 1, 2] * * Array.from(Graph.indices(Graph.dfs(graph))) // => [] * ``` * * @see {@link bfs} for traversal in increasing hop distance * @see {@link dfsPostOrder} for emitting descendants before ancestors * @stability unstable * @category iterators * @since 3.18.0 */ (graph: Graph | MutableGraph, config?: SearchConfig): NodeWalker; }; /** * Creates a lazy breadth-first traversal iterator from the configured start * nodes. * * **When to use** * * Use when visiting nodes in increasing unweighted distance from the start * nodes. * * **Details** * * If no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * * **Gotchas** * * An invalid radius or missing start node throws a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing breadth-first) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Start from a specific node * Array.from(Graph.indices(Graph.bfs(graph, { start: [0] }))) // => [0, 1, 2] * * Array.from(Graph.indices(Graph.bfs(graph))) // => [] * ``` * * @see {@link dfs} for branch-first traversal * @see {@link unweightedDistances} for collecting hop counts * @stability unstable * @category iterators * @since 3.18.0 */ export declare const bfs: { /** * Creates a lazy breadth-first traversal iterator from the configured start * nodes. * * **When to use** * * Use when visiting nodes in increasing unweighted distance from the start * nodes. * * **Details** * * If no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * * **Gotchas** * * An invalid radius or missing start node throws a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing breadth-first) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Start from a specific node * Array.from(Graph.indices(Graph.bfs(graph, { start: [0] }))) // => [0, 1, 2] * * Array.from(Graph.indices(Graph.bfs(graph))) // => [] * ``` * * @see {@link dfs} for branch-first traversal * @see {@link unweightedDistances} for collecting hop counts * @stability unstable * @category iterators * @since 3.18.0 */ (config?: SearchConfig): (graph: Graph | MutableGraph) => NodeWalker; /** * Creates a lazy breadth-first traversal iterator from the configured start * nodes. * * **When to use** * * Use when visiting nodes in increasing unweighted distance from the start * nodes. * * **Details** * * If no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * * **Gotchas** * * An invalid radius or missing start node throws a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing breadth-first) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * // Start from a specific node * Array.from(Graph.indices(Graph.bfs(graph, { start: [0] }))) // => [0, 1, 2] * * Array.from(Graph.indices(Graph.bfs(graph))) // => [] * ``` * * @see {@link dfs} for branch-first traversal * @see {@link unweightedDistances} for collecting hop counts * @stability unstable * @category iterators * @since 3.18.0 */ (graph: Graph | MutableGraph, config?: SearchConfig): NodeWalker; }; /** * Configuration for the topological sort iterator. * * **When to use** * * Use to prioritize specific zero in-degree nodes in a topological sort. * * **Details** * * `initials` optionally supplies zero in-degree node indices used as * prioritized initial queue entries. Topological sorting still includes the * other zero in-degree nodes and produces a complete topological order. * * **Gotchas** * * Throws a `GraphError` when any initial node has incoming edges. * * @stability unstable * @category configuration * @since 3.18.0 */ export interface TopoConfig { readonly initials?: Array; } /** * Creates a lazy topological-order iterator for a directed acyclic graph. * * **When to use** * * Use when processing dependencies so every predecessor is emitted before the * nodes that depend on it. * * **Details** * * The iterator uses Kahn's algorithm. Multiple valid orders may exist; * `initials` prioritizes eligible zero in-degree nodes without excluding other * nodes. * * **Gotchas** * * Undirected or cyclic graphs, missing initial nodes, and initial nodes with * incoming edges throw a `GraphError`. Traversing a mutable graph captures a * snapshot when iteration begins; later mutations are not observed. * * **Example** (Sorting topologically) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * Array.from(Graph.indices(Graph.topo(graph))) // => [0, 1, 2] * ``` * * @see {@link isAcyclic} for checking the required graph property * @stability unstable * @category iterators * @since 3.18.0 */ export declare const topo: { /** * Creates a lazy topological-order iterator for a directed acyclic graph. * * **When to use** * * Use when processing dependencies so every predecessor is emitted before the * nodes that depend on it. * * **Details** * * The iterator uses Kahn's algorithm. Multiple valid orders may exist; * `initials` prioritizes eligible zero in-degree nodes without excluding other * nodes. * * **Gotchas** * * Undirected or cyclic graphs, missing initial nodes, and initial nodes with * incoming edges throw a `GraphError`. Traversing a mutable graph captures a * snapshot when iteration begins; later mutations are not observed. * * **Example** (Sorting topologically) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * Array.from(Graph.indices(Graph.topo(graph))) // => [0, 1, 2] * ``` * * @see {@link isAcyclic} for checking the required graph property * @stability unstable * @category iterators * @since 3.18.0 */ (config?: TopoConfig): (graph: Graph | MutableGraph) => NodeWalker; /** * Creates a lazy topological-order iterator for a directed acyclic graph. * * **When to use** * * Use when processing dependencies so every predecessor is emitted before the * nodes that depend on it. * * **Details** * * The iterator uses Kahn's algorithm. Multiple valid orders may exist; * `initials` prioritizes eligible zero in-degree nodes without excluding other * nodes. * * **Gotchas** * * Undirected or cyclic graphs, missing initial nodes, and initial nodes with * incoming edges throw a `GraphError`. Traversing a mutable graph captures a * snapshot when iteration begins; later mutations are not observed. * * **Example** (Sorting topologically) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 1) * }) * * Array.from(Graph.indices(Graph.topo(graph))) // => [0, 1, 2] * ``` * * @see {@link isAcyclic} for checking the required graph property * @stability unstable * @category iterators * @since 3.18.0 */ (graph: Graph | MutableGraph, config?: TopoConfig): NodeWalker; }; /** * Creates a lazy depth-first postorder traversal iterator from the configured * start nodes. * * **When to use** * * Use when reachable descendants must be emitted before the nodes that lead to * them. * * **Details** * * Nodes are emitted after their reachable descendants have been processed. If * no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * With a finite `radius`, a bounded breadth-first pass first determines * shortest-distance membership before nodes are emitted in postorder. * * **Gotchas** * * Invalid radii and missing start nodes throw a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing in postorder) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const root = Graph.addNode(mutable, "root") * const child1 = Graph.addNode(mutable, "child1") * const child2 = Graph.addNode(mutable, "child2") * Graph.addEdge(mutable, root, child1, 1) * Graph.addEdge(mutable, root, child2, 1) * }) * * // Postorder: children before parents * Array.from(Graph.indices(Graph.dfsPostOrder(graph, { start: [0] }))) // => [1, 2, 0] * ``` * * @see {@link dfs} for emitting nodes when first visited * @stability unstable * @category iterators * @since 3.18.0 */ export declare const dfsPostOrder: { /** * Creates a lazy depth-first postorder traversal iterator from the configured * start nodes. * * **When to use** * * Use when reachable descendants must be emitted before the nodes that lead to * them. * * **Details** * * Nodes are emitted after their reachable descendants have been processed. If * no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * With a finite `radius`, a bounded breadth-first pass first determines * shortest-distance membership before nodes are emitted in postorder. * * **Gotchas** * * Invalid radii and missing start nodes throw a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing in postorder) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const root = Graph.addNode(mutable, "root") * const child1 = Graph.addNode(mutable, "child1") * const child2 = Graph.addNode(mutable, "child2") * Graph.addEdge(mutable, root, child1, 1) * Graph.addEdge(mutable, root, child2, 1) * }) * * // Postorder: children before parents * Array.from(Graph.indices(Graph.dfsPostOrder(graph, { start: [0] }))) // => [1, 2, 0] * ``` * * @see {@link dfs} for emitting nodes when first visited * @stability unstable * @category iterators * @since 3.18.0 */ (config?: SearchConfig): (graph: Graph | MutableGraph) => NodeWalker; /** * Creates a lazy depth-first postorder traversal iterator from the configured * start nodes. * * **When to use** * * Use when reachable descendants must be emitted before the nodes that lead to * them. * * **Details** * * Nodes are emitted after their reachable descendants have been processed. If * no start nodes are supplied, the iterator is empty. The `direction` option * chooses whether to follow outgoing or incoming edges. The `radius` option * limits traversal by edge distance from the start nodes. It accepts * non-negative integers and `Infinity`; omitting it means unbounded traversal. * With a finite `radius`, a bounded breadth-first pass first determines * shortest-distance membership before nodes are emitted in postorder. * * **Gotchas** * * Invalid radii and missing start nodes throw a `GraphError`. Traversing a * mutable graph captures a snapshot when iteration begins; later mutations are * not observed by that iterator. * * **Example** (Traversing in postorder) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const root = Graph.addNode(mutable, "root") * const child1 = Graph.addNode(mutable, "child1") * const child2 = Graph.addNode(mutable, "child2") * Graph.addEdge(mutable, root, child1, 1) * Graph.addEdge(mutable, root, child2, 1) * }) * * // Postorder: children before parents * Array.from(Graph.indices(Graph.dfsPostOrder(graph, { start: [0] }))) // => [1, 2, 0] * ``` * * @see {@link dfs} for emitting nodes when first visited * @stability unstable * @category iterators * @since 3.18.0 */ (graph: Graph | MutableGraph, config?: SearchConfig): NodeWalker; }; /** * Creates a walker over all node index and payload entries in the graph. * * **Details** * * Entries follow graph node order and include all nodes regardless of * connectivity. Use `indices` or `values` to project one side of each entry. * * **Gotchas** * * Mutable graphs are not snapshotted; mutations may affect the remaining * iteration. * * **Example** (Iterating all nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * }) * * Array.from(Graph.indices(Graph.nodes(graph))) // => [0, 1, 2] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ export declare const nodes: (graph: Graph | MutableGraph) => NodeWalker; /** * Creates a walker over all edge index and edge entries in the graph. * * **Details** * * Entries follow graph edge order and include all edges regardless of * connectivity. Use `indices` or `values` to project one side of each entry. * * **Gotchas** * * Mutable graphs are not snapshotted; mutations may affect the remaining * iteration. * * **Example** (Iterating all edges) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const a = Graph.addNode(mutable, "A") * const b = Graph.addNode(mutable, "B") * const c = Graph.addNode(mutable, "C") * Graph.addEdge(mutable, a, b, 1) * Graph.addEdge(mutable, b, c, 2) * }) * * Array.from(Graph.indices(Graph.edges(graph))) // => [0, 1] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ export declare const edges: (graph: Graph | MutableGraph) => EdgeWalker; /** * Configuration for selecting external nodes. * * **When to use** * * Use to configure how `externals` identifies graph boundary nodes when you * need sinks with no outgoing edges or sources with no incoming edges. * * **Details** * * `direction` chooses which missing edge direction makes a node external: * `"outgoing"` selects nodes with no outgoing edges, and `"incoming"` selects * nodes with no incoming edges. If omitted, `direction` defaults to * `"outgoing"`. * * @stability unstable * @category configuration * @since 3.18.0 */ export interface ExternalsConfig { readonly direction?: Direction; } /** * Creates an iterator over external nodes (nodes without edges in the specified direction). * * **When to use** * * Use when locating sources, sinks, or isolated boundary nodes. * * **Details** * * External nodes have no outgoing edges (`direction: "outgoing"`) or no * incoming edges (`direction: "incoming"`). * * **Gotchas** * * For undirected graphs, incoming and outgoing adjacency are equivalent, so * only isolated nodes are external. Mutable graphs are not snapshotted; * mutations may affect the remaining iteration. * * **Example** (Iterating external nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const source = Graph.addNode(mutable, "source") // 0 - no incoming * const middle = Graph.addNode(mutable, "middle") // 1 - has both * const sink = Graph.addNode(mutable, "sink") // 2 - no outgoing * const isolated = Graph.addNode(mutable, "isolated") // 3 - no edges * * Graph.addEdge(mutable, source, middle, 1) * Graph.addEdge(mutable, middle, sink, 2) * }) * * // Nodes with no outgoing edges (sinks + isolated) * Array.from(Graph.indices(Graph.externals(graph, { direction: "outgoing" }))) // => [2, 3] * * // Nodes with no incoming edges (sources + isolated) * Array.from(Graph.indices(Graph.externals(graph, { direction: "incoming" }))) // => [0, 3] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ export declare const externals: { /** * Creates an iterator over external nodes (nodes without edges in the specified direction). * * **When to use** * * Use when locating sources, sinks, or isolated boundary nodes. * * **Details** * * External nodes have no outgoing edges (`direction: "outgoing"`) or no * incoming edges (`direction: "incoming"`). * * **Gotchas** * * For undirected graphs, incoming and outgoing adjacency are equivalent, so * only isolated nodes are external. Mutable graphs are not snapshotted; * mutations may affect the remaining iteration. * * **Example** (Iterating external nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const source = Graph.addNode(mutable, "source") // 0 - no incoming * const middle = Graph.addNode(mutable, "middle") // 1 - has both * const sink = Graph.addNode(mutable, "sink") // 2 - no outgoing * const isolated = Graph.addNode(mutable, "isolated") // 3 - no edges * * Graph.addEdge(mutable, source, middle, 1) * Graph.addEdge(mutable, middle, sink, 2) * }) * * // Nodes with no outgoing edges (sinks + isolated) * Array.from(Graph.indices(Graph.externals(graph, { direction: "outgoing" }))) // => [2, 3] * * // Nodes with no incoming edges (sources + isolated) * Array.from(Graph.indices(Graph.externals(graph, { direction: "incoming" }))) // => [0, 3] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ (config?: ExternalsConfig): (graph: Graph | MutableGraph) => NodeWalker; /** * Creates an iterator over external nodes (nodes without edges in the specified direction). * * **When to use** * * Use when locating sources, sinks, or isolated boundary nodes. * * **Details** * * External nodes have no outgoing edges (`direction: "outgoing"`) or no * incoming edges (`direction: "incoming"`). * * **Gotchas** * * For undirected graphs, incoming and outgoing adjacency are equivalent, so * only isolated nodes are external. Mutable graphs are not snapshotted; * mutations may affect the remaining iteration. * * **Example** (Iterating external nodes) * * ```ts import.meta.vitest * import { Graph } from "effect" * * const graph = Graph.directed((mutable) => { * const source = Graph.addNode(mutable, "source") // 0 - no incoming * const middle = Graph.addNode(mutable, "middle") // 1 - has both * const sink = Graph.addNode(mutable, "sink") // 2 - no outgoing * const isolated = Graph.addNode(mutable, "isolated") // 3 - no edges * * Graph.addEdge(mutable, source, middle, 1) * Graph.addEdge(mutable, middle, sink, 2) * }) * * // Nodes with no outgoing edges (sinks + isolated) * Array.from(Graph.indices(Graph.externals(graph, { direction: "outgoing" }))) // => [2, 3] * * // Nodes with no incoming edges (sources + isolated) * Array.from(Graph.indices(Graph.externals(graph, { direction: "incoming" }))) // => [0, 3] * ``` * * @stability unstable * @category iterators * @since 3.18.0 */ (graph: Graph | MutableGraph, config?: ExternalsConfig): NodeWalker; }; export {}; //# sourceMappingURL=Graph.d.ts.map