<E>(config: BellmanFordConfig<E>): <N, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>
) => Option.Option<PathResult<E>>
<N, E, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
config: BellmanFordConfig<E>
): Option.Option<PathResult<E>>Finds the shortest path from the configured source node to the target node using the Bellman-Ford algorithm.
Details
Negative edge weights are allowed. Returns Option.none() when the target is
unreachable or when a negative cycle affects the path to the target. Throws a
GraphError when either endpoint is missing.
Example (Finding shortest paths with Bellman-Ford)
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) // 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
})
if (result._tag === "Some") {
console.log(result.value.path) // [0, 1, 2] - shortest path A->B->C
console.log(result.value.distance) // 2 - total distance
}export const const bellmanFord: {
<E>(config: BellmanFordConfig<E>): <
N,
T extends Kind = "directed"
>(
graph: Graph<N, E, T> | MutableGraph<N, E, T>
) => Option.Option<PathResult<E>>
<N, E, T extends Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
config: BellmanFordConfig<E>
): Option.Option<PathResult<E>>
}
Finds the shortest path from the configured source node to the target node
using the Bellman-Ford algorithm.
Details
Negative edge weights are allowed. Returns Option.none() when the target is
unreachable or when a negative cycle affects the path to the target. Throws a
GraphError when either endpoint is missing.
Example (Finding shortest paths with Bellman-Ford)
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) // 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
})
if (result._tag === "Some") {
console.log(result.value.path) // [0, 1, 2] - shortest path A->B->C
console.log(result.value.distance) // 2 - total distance
}
bellmanFord: {
<function (type parameter) E in <E>(config: BellmanFordConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E>(
config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config: interface BellmanFordConfig<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.
BellmanFordConfig<function (type parameter) E in <E>(config: BellmanFordConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E>
): <function (type parameter) N in <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>N, function (type parameter) T in <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>T extends type Kind = "directed" | "undirected"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.
Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph: interface Graph<out N, out E, T extends Kind = "directed">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.
Graph<function (type parameter) N in <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>N, function (type parameter) E in <E>(config: BellmanFordConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E, function (type parameter) T in <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>T> | interface MutableGraph<out N, out E, T extends Kind = "directed">Mutable graph interface.
When to use
Use when adding, removing, or updating nodes and edges inside a graph
mutation scope.
MutableGraph<function (type parameter) N in <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>N, function (type parameter) E in <E>(config: BellmanFordConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E, function (type parameter) T in <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>): Option.Option<PathResult<E>>T>) => import OptionOption.type Option<A> = Option.None<A> | Option.Some<A>The Option data type represents optional values. An Option<A> is either
Some<A>, containing a value of type A, or None, representing absence.
When to use
Use to represent initial values that may not yet exist
- Returning from partial functions (not defined for all inputs)
- Managing optional fields in data structures
Namespace containing utility types for Option.
When to use
Use to access type-level helpers associated with Option.
Option<interface PathResult<E>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 indices, total distance,
and traversed edge data.
Details
Contains the node-index path, 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.
PathResult<function (type parameter) E in <E>(config: BellmanFordConfig<E>): <N, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>) => Option.Option<PathResult<E>>E>>
<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>T extends type Kind = "directed" | "undirected"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.
Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>graph: interface Graph<out N, out E, T extends Kind = "directed">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.
Graph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>T> | interface MutableGraph<out N, out E, T extends Kind = "directed">Mutable graph interface.
When to use
Use when adding, removing, or updating nodes and edges inside a graph
mutation scope.
MutableGraph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>T>,
config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config: interface BellmanFordConfig<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.
BellmanFordConfig<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E>
): import OptionOption.type Option<A> = Option.None<A> | Option.Some<A>The Option data type represents optional values. An Option<A> is either
Some<A>, containing a value of type A, or None, representing absence.
When to use
Use to represent initial values that may not yet exist
- Returning from partial functions (not defined for all inputs)
- Managing optional fields in data structures
Namespace containing utility types for Option.
When to use
Use to access type-level helpers associated with Option.
Option<interface PathResult<E>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 indices, total distance,
and traversed edge data.
Details
Contains the node-index path, 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.
PathResult<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E>>
} = import dualdual(2, <function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>T extends type Kind = "directed" | "undirected"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.
Kind = "directed">(
graph: Graph<N, E, T> | MutableGraph<N, E, T>graph: interface Graph<out N, out E, T extends Kind = "directed">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.
Graph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>T> | interface MutableGraph<out N, out E, T extends Kind = "directed">Mutable graph interface.
When to use
Use when adding, removing, or updating nodes and edges inside a graph
mutation scope.
MutableGraph<function (type parameter) N in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>N, function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E, function (type parameter) T in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>T>,
config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config: interface BellmanFordConfig<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.
BellmanFordConfig<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E>
): import OptionOption.type Option<A> = Option.None<A> | Option.Some<A>The Option data type represents optional values. An Option<A> is either
Some<A>, containing a value of type A, or None, representing absence.
When to use
Use to represent initial values that may not yet exist
- Returning from partial functions (not defined for all inputs)
- Managing optional fields in data structures
Namespace containing utility types for Option.
When to use
Use to access type-level helpers associated with Option.
Option<interface PathResult<E>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 indices, total distance,
and traversed edge data.
Details
Contains the node-index path, 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.
PathResult<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E>> => {
// Validate that source and target nodes exist
if (!graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.has(key: number): booleanhas(config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.source: NodeIndexsource)) {
throw const missingNode: (
node: number
) => GraphError
missingNode(config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.source: NodeIndexsource)
}
if (!graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.has(key: number): booleanhas(config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.target: NodeIndextarget)) {
throw const missingNode: (
node: number
) => GraphError
missingNode(config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.target: NodeIndextarget)
}
// Early return if source equals target
if (config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.source: NodeIndexsource === config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.target: NodeIndextarget) {
return import OptionOption.const some: <A>(value: A) => Option<A>Wraps the given value into an Option to represent its presence.
When to use
Use to wrap a known present value as Option
- Returning a successful result from a partial function
Details
- Always returns
Some<A>
- Does not filter
null or undefined; use
fromNullishOr
for that
Example (Wrapping a value)
import { Option } from "effect"
// ┌─── Option<number>
// ▼
const value = Option.some(1)
console.log(value)
// Output: { _id: 'Option', _tag: 'Some', value: 1 }
some({
path: number[]path: [config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.source: NodeIndexsource],
distance: numberdistance: 0,
costs: never[]costs: []
})
}
// Initialize distances and predecessors
const const distances: Map<number, number>distances = new var Map: MapConstructor
new <number, number>(iterable?: Iterable<readonly [number, number]> | null | undefined) => Map<number, number> (+3 overloads)
Map<type NodeIndex = numberNode 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.
NodeIndex, number>()
const const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous = new var Map: MapConstructor
new <number, {
node: NodeIndex;
edgeData: E;
} | null>(iterable?: Iterable<readonly [number, {
node: NodeIndex;
edgeData: E;
} | null]> | null | undefined) => Map<number, {
node: NodeIndex;
edgeData: E;
} | null> (+3 overloads)
Map<type NodeIndex = numberNode 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.
NodeIndex, { node: NodeIndexnode: type NodeIndex = numberNode 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.
NodeIndex; edgeData: EedgeData: function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E } | null>()
// Iterate directly over node keys
for (const const node: numbernode of graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.keys(): MapIterator<number>Returns an iterable of keys in the map
keys()) {
const distances: Map<number, number>distances.Map<number, number>.set(key: number, value: number): Map<number, number>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const node: numbernode, const node: numbernode === config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.source: NodeIndexsource ? 0 : var Infinity: numberInfinity)
const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous.function Map(key: number, value: { node: NodeIndex; edgeData: E } | null): Map<number, { node: NodeIndex; edgeData: E } | null>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const node: numbernode, null)
}
// Collect all edges for relaxation
const const edges: Array<{
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}>
edges: interface Array<T>Array<{ source: NodeIndexsource: type NodeIndex = numberNode 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.
NodeIndex; target: NodeIndextarget: type NodeIndex = numberNode 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.
NodeIndex; weight: numberweight: number; edgeData: EedgeData: function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E }> = []
for (const [, const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData] of graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.edges: Map<EdgeIndex, Edge<E>>edges) {
const const weight: numberweight = config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.cost: (edgeData: E) => numbercost(const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.data)
const edges: Array<{
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}>
edges.function Array(...items: Array<{ source: NodeIndex; target: NodeIndex; weight: number; edgeData: E }>): numberAppends new elements to the end of an array, and returns the new length of the array.
push({
source: numbersource: const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.source,
target: numbertarget: const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.target,
weight: numberweight,
edgeData: EedgeData: const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.data
})
if (graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.type: T extends Kind = "directed"type === "undirected" && const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.source !== const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.target) {
const edges: Array<{
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}>
edges.function Array(...items: Array<{ source: NodeIndex; target: NodeIndex; weight: number; edgeData: E }>): numberAppends new elements to the end of an array, and returns the new length of the array.
push({
source: numbersource: const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.target,
target: numbertarget: const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.source,
weight: numberweight,
edgeData: EedgeData: const edgeData: Edge<E>const edgeData: {
source: number;
target: number;
data: E;
pipe: { <A>(this: A): A; <A, B = never>(this: A, ab: (_: A) => B): B; <A, B = never, C = never>(this: A, ab: (_: A) => B, bc: (_: B) => C): C; <A, B = never, C = never, D = never>(this: A, ab: (_: A) => B, bc: (_: B) => C, cd: (_: C) => D): D; <…;
}
edgeData.data
})
}
}
// Relax edges up to V-1 times
const const nodeCount: numbernodeCount = graph: Graph<N, E, T> | MutableGraph<N, E, T>graph.Proto<out N, out E>.nodes: Map<NodeIndex, N>nodes.Map<K, V>.size: numbersize
for (let let i: numberi = 0; let i: numberi < const nodeCount: numbernodeCount - 1; let i: numberi++) {
let let hasUpdate: booleanhasUpdate = false
for (const const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge of const edges: Array<{
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}>
edges) {
const const sourceDistance: numbersourceDistance = const distances: Map<number, number>distances.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.source: NodeIndexsource)!
const const targetDistance: numbertargetDistance = const distances: Map<number, number>distances.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.target: NodeIndextarget)!
// Relaxation step
if (const sourceDistance: numbersourceDistance !== var Infinity: numberInfinity && const sourceDistance: numbersourceDistance + const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.weight: numberweight < const targetDistance: numbertargetDistance) {
const distances: Map<number, number>distances.Map<number, number>.set(key: number, value: number): Map<number, number>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.target: NodeIndextarget, const sourceDistance: numbersourceDistance + const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.weight: numberweight)
const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous.function Map(key: number, value: { node: NodeIndex; edgeData: E } | null): Map<number, { node: NodeIndex; edgeData: E } | null>Adds a new element with a specified key and value to the Map. If an element with the same key already exists, the element will be updated.
set(const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.target: NodeIndextarget, { node: numbernode: const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.source: NodeIndexsource, edgeData: EedgeData: const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.edgeData: EedgeData })
let hasUpdate: booleanhasUpdate = true
}
}
// Early termination if no updates
if (!let hasUpdate: booleanhasUpdate) {
break
}
}
// Check for negative cycles
for (const const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge of const edges: Array<{
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}>
edges) {
const const sourceDistance: numbersourceDistance = const distances: Map<number, number>distances.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.source: NodeIndexsource)!
const const targetDistance: numbertargetDistance = const distances: Map<number, number>distances.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.target: NodeIndextarget)!
if (const sourceDistance: numbersourceDistance !== var Infinity: numberInfinity && const sourceDistance: numbersourceDistance + const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.weight: numberweight < const targetDistance: numbertargetDistance) {
// Negative cycle detected - check if it affects the path to target
const const affectedNodes: Set<number>affectedNodes = new var Set: SetConstructor
new <number>(iterable?: Iterable<number> | null | undefined) => Set<number> (+1 overload)
Set<type NodeIndex = numberNode 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.
NodeIndex>()
const const queue: number[]queue = [const edge: {
source: NodeIndex
target: NodeIndex
weight: number
edgeData: E
}
edge.target: NodeIndextarget]
while (const queue: number[]queue.Array<number>.length: numberGets or sets the length of the array. This is a number one higher than the highest index in the array.
length > 0) {
const const node: numbernode = const queue: number[]queue.Array<number>.shift(): number | undefinedRemoves the first element from an array and returns it.
If the array is empty, undefined is returned and the array is not modified.
shift()!
if (const affectedNodes: Set<number>affectedNodes.Set<number>.has(value: number): booleanhas(const node: numbernode)) continue
const affectedNodes: Set<number>affectedNodes.Set<number>.add(value: number): Set<number>Appends a new element with a specified value to the end of the Set.
add(const node: numbernode)
// Add all nodes reachable from this node
for (const const neighbor: numberneighbor of const getTraversalNeighbors: <
N,
E,
T extends Kind
>(
graph: Graph<N, E, T> | MutableGraph<N, E, T>,
nodeIndex: NodeIndex,
direction: Direction
) => Array<NodeIndex>
getTraversalNeighbors(graph: Graph<N, E, T> | MutableGraph<N, E, T>graph, const node: numbernode, "outgoing")) {
const queue: number[]queue.Array<number>.push(...items: number[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(const neighbor: numberneighbor)
}
}
// If target is affected by a negative cycle, no shortest path exists.
if (const affectedNodes: Set<number>affectedNodes.Set<number>.has(value: number): booleanhas(config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.target: NodeIndextarget)) {
return import OptionOption.const none: <A = never>() => Option<A>Creates an Option representing the absence of a value.
When to use
Use to represent a missing or uninitialized value, such as returning "no
result" from a function.
Details
- Returns
Option<never>, which is a subtype of Option<A> for any A
- Always returns the same singleton instance
Example (Creating an empty Option)
import { Option } from "effect"
// ┌─── Option<never>
// ▼
const noValue = Option.none()
console.log(noValue)
// Output: { _id: 'Option', _tag: 'None' }
none()
}
}
}
// Check if target is reachable
const const distance: numberdistance = const distances: Map<number, number>distances.Map<number, number>.get(key: number): number | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.target: NodeIndextarget)!
if (const distance: numberdistance === var Infinity: numberInfinity) {
return import OptionOption.const none: <A = never>() => Option<A>Creates an Option representing the absence of a value.
When to use
Use to represent a missing or uninitialized value, such as returning "no
result" from a function.
Details
- Returns
Option<never>, which is a subtype of Option<A> for any A
- Always returns the same singleton instance
Example (Creating an empty Option)
import { Option } from "effect"
// ┌─── Option<never>
// ▼
const noValue = Option.none()
console.log(noValue)
// Output: { _id: 'Option', _tag: 'None' }
none() // No path exists
}
// Reconstruct path
const const path: Array<NodeIndex>path: interface Array<T>Array<type NodeIndex = numberNode 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.
NodeIndex> = []
const const costs: E[]costs: interface Array<T>Array<function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E> = []
let let currentNode: NodeIndex | nullcurrentNode: type NodeIndex = numberNode 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.
NodeIndex | null = config: BellmanFordConfig<E>(parameter) config: {
source: NodeIndex;
target: NodeIndex;
cost: (edgeData: E) => number;
}
config.BellmanFordConfig<E>.target: NodeIndextarget
while (let currentNode: NodeIndex | nullcurrentNode !== null) {
const path: Array<NodeIndex>path.Array<number>.unshift(...items: number[]): numberInserts new elements at the start of an array, and returns the new length of the array.
unshift(let currentNode: NodeIndex | nullcurrentNode)
const const prev: {
node: NodeIndex
edgeData: E
} | null
prev: { node: NodeIndexnode: type NodeIndex = numberNode 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.
NodeIndex; edgeData: EedgeData: function (type parameter) E in <N, E, T extends Kind = "directed">(graph: Graph<N, E, T> | MutableGraph<N, E, T>, config: BellmanFordConfig<E>): Option.Option<PathResult<E>>E } | null = const previous: Map<
number,
{ node: NodeIndex; edgeData: E } | null
>
previous.function Map(key: number): { node: NodeIndex; edgeData: E } | null | undefinedReturns a specified element from the Map object. If the value that is associated to the provided key is an object, then you will get a reference to that object and any change made to that object will effectively modify it inside the Map.
get(let currentNode: NodeIndex | nullcurrentNode)!
if (const prev: {
node: NodeIndex
edgeData: E
} | null
prev !== null) {
const costs: E[]costs.Array<E>.unshift(...items: E[]): numberInserts new elements at the start of an array, and returns the new length of the array.
unshift(const prev: {
node: NodeIndex
edgeData: E
} | null
prev.edgeData: EedgeData)
let currentNode: NodeIndex | nullcurrentNode = const prev: {
node: NodeIndex
edgeData: E
} | null
prev.node: NodeIndexnode
} else {
let currentNode: NodeIndex | nullcurrentNode = null
}
}
return import OptionOption.const some: <A>(value: A) => Option<A>Wraps the given value into an Option to represent its presence.
When to use
Use to wrap a known present value as Option
- Returning a successful result from a partial function
Details
- Always returns
Some<A>
- Does not filter
null or undefined; use
fromNullishOr
for that
Example (Wrapping a value)
import { Option } from "effect"
// ┌─── Option<number>
// ▼
const value = Option.some(1)
console.log(value)
// Output: { _id: 'Option', _tag: 'Some', value: 1 }
some({
path: number[]path,
distance: numberdistance,
costs: E[]costs
})
})