/**
 * 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<out E> {
    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<out N> {
    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<out E> extends Edge<E> {
    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<out N, out E, out T extends Kind> {
    readonly type: T;
    readonly nodes: ReadonlyArray<IndexedNode<N>>;
    readonly edges: ReadonlyArray<IndexedEdge<E>>;
}
/**
 * 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<out N, out E, T extends Kind = "directed"> extends Iterable<readonly [NodeIndex, N]>, Equal.Equal, Pipeable, Inspectable {
    readonly [TypeId]: Graph.Variance<N, E>;
    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<out N, out E> {
        readonly _N: Covariant<N>;
        readonly _E: Covariant<E>;
    }
}
/**
 * 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<in out N, in out E, T extends Kind = "directed"> extends Iterable<readonly [NodeIndex, N]>, Equal.Equal, Pipeable, Inspectable {
    readonly [TypeId]: MutableGraph.Variance<N, E>;
    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<in out N, in out E> {
        readonly _N: Invariant<N>;
        readonly _E: Invariant<E>;
    }
}
/**
 * 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<N, E>` is a `Graph<N, E, "directed">` 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<N, E> = Graph<N, E, "directed">;
/**
 * 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<N, E>` is a `Graph<N, E, "undirected">`.
 *
 * @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<N, E> = Graph<N, E, "undirected">;
/**
 * 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<N, E> = MutableGraph<N, E, "directed">;
/**
 * 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<N, E> = MutableGraph<N, E, "undirected">;
declare const GraphError_base: new <A extends Record<string, any> = {}>(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<A>;
/**
 * 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: <N = unknown, E = unknown, T extends Kind = Kind, U = never>(u: U | Graph<N, E, T> | MutableGraph<N, E, T>) => u is Graph<N, E, T> | MutableGraph<N, E, T>;
/**
 * 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: <N, E, T extends Kind>(snapshot: Snapshot<N, E, T>) => Graph<N, E, T>;
/**
 * 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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Snapshot<N, E, T>;
/**
 * 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<string, number>((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: <T extends Kind>(type: T) => <N, E>(mutate?: (mutable: MutableGraph<N, E, T>) => undefined) => Graph<N, E, T>;
/**
 * 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<string, string>((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: <N, E>(mutate?: (mutable: MutableDirectedGraph<N, E>) => undefined) => DirectedGraph<N, E>;
/**
 * 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<string, string>((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: <N, E>(mutate?: (mutable: MutableUndirectedGraph<N, E>) => undefined) => UndirectedGraph<N, E>;
/**
 * 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<string, number>()
 * 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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T>) => MutableGraph<N, E, T>;
/**
 * 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<string, number>()
 * 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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>) => Graph<N, E, T>;
/**
 * 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<string, number>()
 * 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<string, number>()
     * 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
     */
    <N, E, T extends Kind = "directed">(f: (mutable: MutableGraph<N, E, T>) => undefined): (graph: Graph<N, E, T>) => Graph<N, E, T>;
    /**
     * 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<string, number>()
     * 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T>, f: (mutable: MutableGraph<N, E, T>) => undefined): Graph<N, E, T>;
};
/**
 * 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<N, E, NI = N, EI = E> {
    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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(that: Graph<N, E, T>, options?: IdentityOptions<N, E, NI, EI>): (self: Graph<N, E, NoInfer<T>>) => Graph<N, E, T>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(self: Graph<N, E, T>, that: Graph<N, E, NoInfer<T>>, options?: IdentityOptions<N, E, NI, EI>): Graph<N, E, T>;
};
/**
 * 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<string, string>((mutable) => {
 *   const a = Graph.addNode(mutable, "A")
 *   const b = Graph.addNode(mutable, "B")
 *   Graph.addEdge(mutable, a, b, "shared")
 * })
 *
 * const right = Graph.directed<string, string>((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<string, string>((mutable) => {
     *   const a = Graph.addNode(mutable, "A")
     *   const b = Graph.addNode(mutable, "B")
     *   Graph.addEdge(mutable, a, b, "shared")
     * })
     *
     * const right = Graph.directed<string, string>((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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(that: Graph<N, E, T>, options?: IdentityOptions<N, E, NI, EI>): (self: Graph<N, E, NoInfer<T>>) => Graph<N, E, T>;
    /**
     * 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<string, string>((mutable) => {
     *   const a = Graph.addNode(mutable, "A")
     *   const b = Graph.addNode(mutable, "B")
     *   Graph.addEdge(mutable, a, b, "shared")
     * })
     *
     * const right = Graph.directed<string, string>((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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(self: Graph<N, E, T>, that: Graph<N, E, NoInfer<T>>, options?: IdentityOptions<N, E, NI, EI>): Graph<N, E, T>;
};
/**
 * 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<string, string>((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<string, string>((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<string, string>((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<string, string>((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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(that: Graph<N, E, T>, options?: IdentityOptions<N, E, NI, EI>): (self: Graph<N, E, NoInfer<T>>) => Graph<N, E, T>;
    /**
     * 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<string, string>((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<string, string>((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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(self: Graph<N, E, T>, that: Graph<N, E, NoInfer<T>>, options?: IdentityOptions<N, E, NI, EI>): Graph<N, E, T>;
};
/**
 * 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<string, string>((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<string, string>((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<string, string>((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<string, string>((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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(that: Graph<N, E, T>, options?: IdentityOptions<N, E, NI, EI>): (self: Graph<N, E, NoInfer<T>>) => Graph<N, E, T>;
    /**
     * 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<string, string>((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<string, string>((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
     */
    <N, E, T extends Kind = "directed", NI = N, EI = E>(self: Graph<N, E, T>, that: Graph<N, E, NoInfer<T>>, options?: IdentityOptions<N, E, NI, EI>): Graph<N, E, T>;
};
/**
 * 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<string, string>((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<string, string>((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
     */
    <N, E>(createEdge: (source: N, target: N) => E): <T extends Kind = "directed">(self: Graph<N, E, T>) => Graph<N, E, T>;
    /**
     * 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<string, string>((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
     */
    <N, E, T extends Kind = "directed">(self: Graph<N, E, T>, createEdge: (source: N, target: N) => E): Graph<N, E, T>;
};
/**
 * 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<string, string>((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<string, string>((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): <N, E, T extends Kind = "directed">(self: Graph<N, E, T>) => Graph<N, E, T>;
    /**
     * 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<string, string>((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
     */
    <N, E, T extends Kind = "directed">(self: Graph<N, E, T>, nodeIndex: NodeIndex, options?: NeighborhoodConfig): Graph<N, E, T>;
};
/**
 * 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<NodeIndex>): <N, E, T extends Kind = "directed">(self: Graph<N, E, T>) => Graph<N, E, T>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed">(self: Graph<N, E, T>, nodeIndices: Iterable<NodeIndex>): Graph<N, E, T>;
};
/**
 * 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
     */
    <N, E, T extends Kind>(that: Graph<N, E, T>): (self: Graph<N, E, NoInfer<T>>) => Graph<N, E, T>;
    /**
     * 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
     */
    <N, E, T extends Kind>(self: Graph<N, E, T>, that: Graph<N, E, NoInfer<T>>): Graph<N, E, T>;
};
/**
 * 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<string, number>(), (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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>(), (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<string, number>(), (mutable) => {
     *   Graph.addNode(mutable, "Node A")
     * })
     *
     * Graph.getNode(graph, 0) // => Option.some("Node A")
     * ```
     *
     * @stability unstable
     * @category getters
     * @since 3.18.0
     */
    (nodeIndex: NodeIndex): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<N>;
    /**
     * 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<string, number>(), (mutable) => {
     *   Graph.addNode(mutable, "Node A")
     * })
     *
     * Graph.getNode(graph, 0) // => Option.some("Node A")
     * ```
     *
     * @stability unstable
     * @category getters
     * @since 3.18.0
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: NodeIndex): Option.Option<N>;
};
/**
 * 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<string, number>(), (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<string, number>(), (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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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<string, number>(), (mutable) => {
     *   Graph.addNode(mutable, "Node A")
     * })
     *
     * Graph.hasNode(graph, 0) // => true
     * Graph.hasNode(graph, 999) // => false
     * ```
     *
     * @stability unstable
     * @category predicates
     * @since 3.18.0
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, 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<string, number>()
 * 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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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<string, number>(), (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<string, number>(), (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
     */
    <N>(predicate: (data: N) => boolean): <E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<NodeIndex>;
    /**
     * 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: N) => boolean): Option.Option<NodeIndex>;
};
/**
 * 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<string, number>(), (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<string, number>(), (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
     */
    <N>(predicate: (data: N) => boolean): <E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Array<NodeIndex>;
    /**
     * 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: N) => boolean): Array<NodeIndex>;
};
/**
 * 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<string, number>(), (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<string, number>(), (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
     */
    <E>(predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<EdgeIndex>;
    /**
     * 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): Option.Option<EdgeIndex>;
};
/**
 * 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<string, number>(), (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<string, number>(), (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
     */
    <E>(predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Array<EdgeIndex>;
    /**
     * 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, predicate: (data: E, source: NodeIndex, target: NodeIndex) => boolean): Array<EdgeIndex>;
};
/**
 * 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>(), (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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>) => 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: N) => Option.Option<N>) => 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, f: (data: E) => Option.Option<E>) => 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>((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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>(), (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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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<string, number>(), (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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, nodeIndices: Iterable<NodeIndex>) => 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<string, number>(), (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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, 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: <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, edgeIndices: Iterable<EdgeIndex>) => 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<string, number>(), (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<string, number>(), (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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<Edge<E>>;
    /**
     * 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, edgeIndex: EdgeIndex): Option.Option<Edge<E>>;
};
/**
 * 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<string, number>(), (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<string, number>(), (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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, 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<string, number>()
 * 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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Array<EdgeIndex>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: NodeIndex): Array<EdgeIndex>;
};
/**
 * 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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Array<EdgeIndex>;
    /**
     * 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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: NodeIndex): Array<EdgeIndex>;
};
/**
 * 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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Array<EdgeIndex>;
    /**
     * 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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: NodeIndex): Array<EdgeIndex>;
};
/**
 * 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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Array<EdgeIndex>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex): Array<EdgeIndex>;
};
/**
 * 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): <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => 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
     */
    <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">, 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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => 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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, 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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => 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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, 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<string, number>(), (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<string, number>(), (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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Array<NodeIndex>;
    /**
     * 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, nodeIndex: NodeIndex): Array<NodeIndex>;
};
/**
 * 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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Array<NodeIndex>;
    /**
     * 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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: NodeIndex): Array<NodeIndex>;
};
/**
 * 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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Array<NodeIndex>;
    /**
     * 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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: NodeIndex): Array<NodeIndex>;
};
/**
 * 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<string, string>((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<string, string>((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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Array<NodeIndex>;
    /**
     * 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<string, string>((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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, nodeIndex: NodeIndex, direction: Direction): Array<NodeIndex>;
};
/**
 * 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<string, number> = {
 *   nodeLabel: (data) => `Node: ${data}`,
 *   edgeLabel: (data) => `Weight: ${data}`
 * }
 *
 * // Complete options with graph naming
 * const namedOptions: Graph.GraphVizOptions<string, string> = {
 *   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<N, E> {
    /**
     * 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<string, number>(), (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<string, number>(), (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
     */
    <N, E>(options?: GraphVizOptions<N, E>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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<string, number>(), (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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, options?: GraphVizOptions<N, E>): 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<string, string> = {
 *   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<string, string> = {
 *   direction: "LR"
 * }
 *
 * // Vertical hierarchy (default)
 * const verticalOptions: Graph.MermaidOptions<string, string> = {
 *   direction: "TB"
 * }
 *
 * // Bottom-up flow
 * const bottomUpOptions: Graph.MermaidOptions<string, string> = {
 *   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<string, string> = {
 *   diagramType: "flowchart"
 * }
 *
 * // Force graph format (shows undirected connections)
 * const graphOptions: Graph.MermaidOptions<string, string> = {
 *   diagramType: "graph"
 * }
 *
 * // Auto-detection (recommended, default behavior)
 * const autoOptions: Graph.MermaidOptions<string, string> = {}
 * 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<string, number> = {
 *   nodeLabel: (data) => `Node: ${data}`,
 *   edgeLabel: (data) => `Weight: ${data}`
 * }
 *
 * // Advanced options with all features
 * const advancedOptions: Graph.MermaidOptions<string, string> = {
 *   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<N, E> {
    /**
     * 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<string, string>((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<string, string>((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
     */
    <N, E>(options?: MermaidOptions<N, E>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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<string, string>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, options?: MermaidOptions<N, E>): 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<string, string>((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<NodeIndex>;
    readonly edges: Array<EdgeIndex>;
}
/**
 * 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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<CycleResult>;
/**
 * 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<string, string>((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<string, string>((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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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<string, string>((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<string, string>((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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => 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<string, string>((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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => Array<BipartiteMatch>;
/**
 * 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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Map<NodeIndex, number>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, source: NodeIndex, options?: ReachabilityConfig): Map<NodeIndex, number>;
};
/**
 * 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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, 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<string, string>((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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => Array<Array<NodeIndex>>;
/**
 * 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<void, void>((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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => Array<EdgeIndex>;
/**
 * 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<void, void>((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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => Array<NodeIndex>;
/**
 * 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<void, void>((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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => Array<Array<NodeIndex>>;
/**
 * 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<E> {
    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<EdgeIndex, number>;
    readonly cut: Array<EdgeIndex>;
}
/**
 * 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<EdgeIndex>;
    readonly source: Array<NodeIndex>;
    readonly target: Array<NodeIndex>;
}
/**
 * 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<string, number>((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<string, number>((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
     */
    <E>(config: MaximumFlowConfig<E>): <N>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => 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<string, number>((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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, config: MaximumFlowConfig<E>): 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<string, number>((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<string, number>((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
     */
    <E>(config: MaximumFlowConfig<E>): <N>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => 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<string, number>((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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, config: MaximumFlowConfig<E>): 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: <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Array<Array<NodeIndex>>;
/**
 * 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<string, string>((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: <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Array<Array<NodeIndex>>;
/**
 * 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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => 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: <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => 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: <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => 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: <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => 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
     */
    <E>(cost: (edgeData: E) => number): <N>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">) => Graph<N, E, "undirected">;
    /**
     * 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
     */
    <N, E>(graph: Graph<N, E, "undirected"> | MutableGraph<N, E, "undirected">, cost: (edgeData: E) => number): Graph<N, E, "undirected">;
};
/**
 * 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: <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => Graph<N, E, "directed">;
/**
 * 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<E> {
    readonly path: Array<NodeIndex>;
    readonly edges: Array<EdgeIndex>;
    readonly distance: number;
    readonly costs: Array<E>;
}
/**
 * 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<E> {
    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<string, number>((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<string, number>((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
     */
    <E>(config: DijkstraConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>;
    /**
     * 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<string, number>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: DijkstraConfig<E>): Option.Option<PathResult<E>>;
};
/**
 * 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<E> {
    readonly distances: Map<NodeIndex, Map<NodeIndex, number>>;
    readonly paths: Map<NodeIndex, Map<NodeIndex, Array<NodeIndex> | null>>;
    readonly edges: Map<NodeIndex, Map<NodeIndex, Array<EdgeIndex>>>;
    readonly costs: Map<NodeIndex, Map<NodeIndex, Array<E>>>;
}
/**
 * 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<string, number>((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<string, number>((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
     */
    <E>(cost: (edgeData: E) => number): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => AllPairsResult<E>;
    /**
     * 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<string, number>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, cost: (edgeData: E) => number): AllPairsResult<E>;
};
/**
 * 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<E, N> {
    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
     */
    <E, N>(config: AstarConfig<E, N>): <T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AstarConfig<E, N>): Option.Option<PathResult<E>>;
};
/**
 * 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<E> {
    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<string, number>((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<string, number>((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
     */
    <E>(config: BellmanFordConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>;
    /**
     * 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<string, number>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>;
};
/**
 * 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<E> extends Iterable<PathResult<E>> {
}
/**
 * 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<E> extends DijkstraConfig<E> {
    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
     */
    <E>(config: SimplePathsConfig): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => PathWalker<E>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: SimplePathsConfig): PathWalker<E>;
};
/**
 * 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
     */
    <E>(config: AllShortestPathsConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => PathWalker<E>;
    /**
     * 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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: AllShortestPathsConfig<E>): PathWalker<E>;
};
/**
 * 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<string, number>((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<string> = Graph.dfs(graph, { start: [0] })
 * const allNodes: Graph.NodeWalker<string> = Graph.nodes(graph)
 *
 * // Common interface for working with node iterables
 * function processNodes<N>(nodeIterable: Graph.NodeWalker<N>): Array<number> {
 *   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<T, N> 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<string, number>((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: <U>(f: (index: T, data: N) => U) => Iterable<U>;
    constructor(visit: <U>(f: (index: T, data: N) => U) => Iterable<U>);
}
/**
 * Type alias for node iteration using Walker.
 * NodeWalker is represented as Walker<NodeIndex, N>.
 *
 * **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<N> = Walker<NodeIndex, N>;
/**
 * Type alias for edge iteration using Walker.
 * EdgeWalker is represented as Walker<EdgeIndex, Edge<E>>.
 *
 * **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<E> = Walker<EdgeIndex, Edge<E>>;
/**
 * 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<string, number>((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: <T, N>(walker: Walker<T, N>) => Iterable<T>;
/**
 * 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<string, number>((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: <T, N>(walker: Walker<T, N>) => Iterable<N>;
/**
 * 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<string, number>((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: <T, N>(walker: Walker<T, N>) => 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<NodeIndex>;
    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<string, number>((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<string, number>((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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => NodeWalker<N>;
    /**
     * 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<string, number>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: SearchConfig): NodeWalker<N>;
};
/**
 * 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<string, number>((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<string, number>((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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => NodeWalker<N>;
    /**
     * 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<string, number>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: SearchConfig): NodeWalker<N>;
};
/**
 * 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<NodeIndex>;
}
/**
 * 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<string, number>((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<string, number>((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): <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">) => NodeWalker<N>;
    /**
     * 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<string, number>((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
     */
    <N, E>(graph: Graph<N, E, "directed"> | MutableGraph<N, E, "directed">, config?: TopoConfig): NodeWalker<N>;
};
/**
 * 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<string, number>((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<string, number>((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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => NodeWalker<N>;
    /**
     * 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<string, number>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: SearchConfig): NodeWalker<N>;
};
/**
 * 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<string, number>((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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => NodeWalker<N>;
/**
 * 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<string, number>((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: <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => EdgeWalker<E>;
/**
 * 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<string, number>((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<string, number>((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): <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => NodeWalker<N>;
    /**
     * 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<string, number>((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
     */
    <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config?: ExternalsConfig): NodeWalker<N>;
};
export {};
//# sourceMappingURL=Graph.d.ts.map