<N, E, T extends Kind = "directed">(
mutable: MutableGraph<N, E, T>,
source: NodeIndex,
target: NodeIndex,
data: E
): EdgeIndexAdds 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
Creates an Edge with the source, target, and data at the next edge index,
updates adjacency indexes, and increments the graph's next edge index.
Undirected graphs register the same edge for both endpoints.
Gotchas
The source and target nodes must already exist in the mutable graph; missing
endpoints throw a GraphError.
Example (Adding edges)
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)
console.log(edge) // EdgeIndex with value 0
})export const const addEdge: <
N,
E,
T extends Kind = "directed"
>(
mutable: MutableGraph<N, E, T>,
source: NodeIndex,
target: NodeIndex,
data: E
) => EdgeIndex
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
Creates an Edge with the source, target, and data at the next edge index,
updates adjacency indexes, and increments the graph's next edge index.
Undirected graphs register the same edge for both endpoints.
Gotchas
The source and target nodes must already exist in the mutable graph; missing
endpoints throw a GraphError.
Example (Adding edges)
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)
console.log(edge) // EdgeIndex with value 0
})
addEdge = <function (type parameter) N in <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E): EdgeIndexN, function (type parameter) E in <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E): EdgeIndexE, function (type parameter) T in <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E): EdgeIndexT 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">(
mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable: 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">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E): EdgeIndexN, function (type parameter) E in <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E): EdgeIndexE, function (type parameter) T in <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E): EdgeIndexT>,
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,
data: Edata: function (type parameter) E in <N, E, T extends Kind = "directed">(mutable: MutableGraph<N, E, T>, source: NodeIndex, target: NodeIndex, data: E): EdgeIndexE
): type EdgeIndex = numberEdge 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.
EdgeIndex => {
// Validate that both nodes exist
if (!mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<N, E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.has(key: number): booleanhas(source: NodeIndexsource)) {
throw const missingNode: (
node: number
) => GraphError
missingNode(source: NodeIndexsource)
}
if (!mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<N, E>.nodes: Map<NodeIndex, N>nodes.Map<number, N>.has(key: number): booleanhas(target: NodeIndextarget)) {
throw const missingNode: (
node: number
) => GraphError
missingNode(target: NodeIndextarget)
}
const const edgeIndex: numberedgeIndex = mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<out N, out E>.nextEdgeIndex: EdgeIndexnextEdgeIndex
// Create edge data
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 = new constructor Edge<unknown>(): Edge<unknown>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.
Edge({ source: numbersource, target: numbertarget, data: Edata })
mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<N, E>.edges: Map<EdgeIndex, Edge<E>>edges.Map<number, Edge<E>>.set(key: number, value: Edge<E>): Map<number, Edge<E>>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 edgeIndex: numberedgeIndex, 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)
// Update adjacency lists
const const sourceAdjacency:
| number[]
| undefined
sourceAdjacency = mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<out N, out E>.adjacency: Map<NodeIndex, Array<EdgeIndex>>adjacency.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(source: NodeIndexsource)
if (const sourceAdjacency:
| number[]
| undefined
sourceAdjacency !== var undefinedundefined) {
const sourceAdjacency: number[]sourceAdjacency.Array<number>.push(...items: number[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(const edgeIndex: numberedgeIndex)
}
const const targetReverseAdjacency:
| number[]
| undefined
targetReverseAdjacency = mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<out N, out E>.reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>reverseAdjacency.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(target: NodeIndextarget)
if (const targetReverseAdjacency:
| number[]
| undefined
targetReverseAdjacency !== var undefinedundefined) {
const targetReverseAdjacency: number[]targetReverseAdjacency.Array<number>.push(...items: number[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(const edgeIndex: numberedgeIndex)
}
// For undirected graphs, add reverse connections
if (mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.MutableGraph<N, E, T>.type: T extends Kind = "directed"type === "undirected") {
const const targetAdjacency:
| number[]
| undefined
targetAdjacency = mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<out N, out E>.adjacency: Map<NodeIndex, Array<EdgeIndex>>adjacency.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(target: NodeIndextarget)
if (const targetAdjacency:
| number[]
| undefined
targetAdjacency !== var undefinedundefined) {
const targetAdjacency: number[]targetAdjacency.Array<number>.push(...items: number[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(const edgeIndex: numberedgeIndex)
}
const const sourceReverseAdjacency:
| number[]
| undefined
sourceReverseAdjacency = mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<out N, out E>.reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>reverseAdjacency.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(source: NodeIndexsource)
if (const sourceReverseAdjacency:
| number[]
| undefined
sourceReverseAdjacency !== var undefinedundefined) {
const sourceReverseAdjacency: number[]sourceReverseAdjacency.Array<number>.push(...items: number[]): numberAppends new elements to the end of an array, and returns the new length of the array.
push(const edgeIndex: numberedgeIndex)
}
}
// Update allocators
mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<out N, out E>.nextEdgeIndex: EdgeIndexnextEdgeIndex = mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable.Proto<out N, out E>.nextEdgeIndex: EdgeIndexnextEdgeIndex + 1
// Only invalidate cycle flag if the graph was acyclic
// Adding edges cannot remove cycles from cyclic graphs
const invalidateCycleFlagOnAddition: <
N,
E,
T extends Kind = "directed"
>(
mutable: MutableGraph<N, E, T>
) => void
invalidateCycleFlagOnAddition(mutable: MutableGraph<N, E, T>(parameter) mutable: {
type: T;
mutable: true;
nodes: Map<NodeIndex, N>;
edges: Map<EdgeIndex, Edge<E>>;
adjacency: Map<NodeIndex, Array<EdgeIndex>>;
reverseAdjacency: Map<NodeIndex, Array<EdgeIndex>>;
nextNodeIndex: NodeIndex;
nextEdgeIndex: EdgeIndex;
acyclic: Option.Option<boolean>;
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; <…;
toString: () => string;
toJSON: () => unknown;
}
mutable)
return const edgeIndex: numberedgeIndex
}