architecture/network/connect

Connection-editing chapter for single-edge graph surgery.

This folder owns the smallest structural change a Network can make: add or remove one directed edge while keeping graph invariants, gating state, and execution caches honest. Higher-level builders may connect layers or groups in bulk, but they still depend on the legality and bookkeeping rules taught here.

The important distinction is between edge creation and edge registration. Node.connect() can manufacture one or more low-level connection objects, but the network still has to decide whether those edges are legal in the current topology policy, whether they belong in normal or self-connection storage, and whether cached topological or slab views must be invalidated.

Acyclic mode makes that policy visible. In feed-forward configurations this chapter refuses back-edges and self-edges that would violate the intended execution order. In unconstrained mode the same surface accepts those edits and simply keeps the runtime collections synchronized. That lets callers ask for structural edits without duplicating the topology rules everywhere else.

The matching remove path is equally educational. Disconnecting one edge is not just a splice from an array. If the edge is gated, the gating linkage has to be released first. After that, structural caches are marked dirty so the next activation or slab rebuild sees the new graph instead of a stale one.

flowchart LR
  classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
  classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;

  Request[connect request]:::base --> Guard[acyclic legality check]:::accent
  Guard --> Create[Node.connect creates low-level edges]:::base
  Create --> Register[classify self-edge or standard edge]:::base
  Register --> Dirty[mark topology and slab caches dirty]:::base
flowchart TD
  classDef base fill:#08131f,stroke:#1ea7ff,color:#dff6ff,stroke-width:1px;
  classDef accent fill:#0f2233,stroke:#ffd166,color:#fff4cc,stroke-width:1.5px;

  Mode[topology mode]:::accent --> FeedForward[feed-forward<br/>reject back-edges]:::base
  Mode --> Unconstrained[unconstrained<br/>allow recurrent edits]:::base
  FeedForward --> Collections[network collections stay valid]:::base
  Unconstrained --> Collections

For background on the scheduling constraint behind acyclic mode, see Wikipedia contributors, Topological sorting. The legality checks in this folder protect the execution order assumptions that feed-forward activation relies on.

Example: add one explicit edge between two nodes.

const [edge] = network.connect(sourceNode, targetNode, 0.5);
console.log(edge.weight);

Example: remove one existing edge and let the network invalidate its cached structure for the next run.

network.disconnect(sourceNode, targetNode);

Practical reading order:

  1. Start here for the public connect() and disconnect() semantics.
  2. Continue into network.connect.create.utils.ts for edge creation, registration, and acyclic guards.
  3. Continue into network.connect.remove.utils.ts for disconnect cleanup and gated-edge removal behavior.
  4. Finish with network.connect.utils.types.ts when you need the internal state shape shared across both flows.

architecture/network/connect/network.connect.utils.ts

connect

connect(
  from: default,
  to: default,
  weight: number | undefined,
): default[]

Create and register one (or multiple) directed connection objects between two nodes.

Some node types (or future composite structures) may return several low‑level connections when their {@link Node.connect} is invoked (e.g., expanded recurrent templates). For that reason this function always treats the result as an array and appends each edge to the appropriate collection.

Algorithm outline:

  1. (Acyclic guard) If acyclicity is enforced and the source node appears after the target node in the network's node ordering, abort early and return an empty array (prevents back‑edge creation).
  2. Delegate to sourceNode.connect(targetNode, weight) to build the raw Connection object(s).
  3. For each created connection: a. If it's a self‑connection: either ignore (acyclic mode) or store in selfconns. b. Otherwise store in standard connections array.
  4. If at least one connection was added, mark structural caches dirty (_topoDirty & _slabDirty) so lazy rebuild can occur before the next forward pass.

Complexity:

Edge cases & invariants:

Parameters:

Returns: Array of created {@link Connection} objects (possibly empty if acyclicity rejected the edge).

Example:

const [edge] = net.connect(nodeA, nodeB, 0.5);

disconnect

disconnect(
  from: default,
  to: default,
): void

Remove (at most) one directed connection from source 'from' to target 'to'.

Only a single direct edge is removed because typical graph configurations maintain at most one logical connection between a given pair of nodes (excluding potential future multi‑edge semantics). If the target edge is gated we first call {@link Network.ungate} to maintain gating invariants (ensuring the gater node's internal gate list remains consistent).

Algorithm outline:

  1. Choose the correct list (selfconns vs connections) based on whether from === to.
  2. Linear scan to find the first edge with matching endpoints.
  3. If gated, ungate to detach gater bookkeeping.
  4. Splice the edge out; exit loop (only one expected).
  5. Delegate per‑node cleanup via from.disconnect(to) (clears reverse references, traces, etc.).
  6. Mark structural caches dirty for lazy recomputation.

Complexity:

Idempotence: If no such edge exists we still perform node-level disconnect and flag caches dirty – this conservative approach simplifies callers (they need not pre‑check existence).

Parameters:

Example:

net.disconnect(nodeA, nodeB);

architecture/network/connect/network.connect.utils.types.ts

NetworkInternals

Internal network state shape shared by connect utility helper modules.

architecture/network/connect/network.connect.create.utils.ts

createConnectionsFromSourceNode

createConnectionsFromSourceNode(
  sourceNode: default,
  targetNode: default,
  initialWeight: number | undefined,
): default[]

Build one or more low-level connection objects from source node to target node.

Parameters:

Returns: Created low-level connection objects.

markConnectionCachesDirtyWhenNeeded

markConnectionCachesDirtyWhenNeeded(
  internalState: ConnectNetworkInternals,
  createdConnectionCount: number,
): void

Mark topology and slab caches dirty when connection creation occurred.

Parameters:

Returns: Nothing.

registerCreatedConnections

registerCreatedConnections(
  network: default,
  internalState: ConnectNetworkInternals,
  sourceNode: default,
  targetNode: default,
  createdConnections: default[],
): void

Register created connections in either normal-connection or self-connection storage.

Parameters:

Returns: Nothing.

registerSingleCreatedConnection

registerSingleCreatedConnection(
  network: default,
  internalState: ConnectNetworkInternals,
  isSelfConnection: boolean,
  createdConnection: default,
): void

Register one created connection in the appropriate collection.

Parameters:

Returns: Nothing.

shouldRejectConnectionForAcyclicMode

shouldRejectConnectionForAcyclicMode(
  network: default,
  internalState: ConnectNetworkInternals,
  sourceNode: default,
  targetNode: default,
): boolean

Determine whether an edge must be rejected to preserve acyclic ordering.

Parameters:

Returns: True when edge should be rejected.

architecture/network/connect/network.connect.remove.utils.ts

disconnectNodes

disconnectNodes(
  sourceNode: default,
  targetNode: default,
): void

Delegate per-node disconnect cleanup.

Parameters:

Returns: Nothing.

findConnectionIndex

findConnectionIndex(
  candidateConnections: default[],
  sourceNode: default,
  targetNode: default,
): number

Find index of the first connection matching source and target nodes.

Parameters:

Returns: Matching index or -1 when no edge is found.

markStructureCachesDirty

markStructureCachesDirty(
  internalState: ConnectNetworkInternals,
): void

Mark topology/slab caches dirty after structural mutation.

Parameters:

Returns: Nothing.

removeConnectionAtIndex

removeConnectionAtIndex(
  network: default,
  candidateConnections: default[],
  targetConnectionIndex: number,
): void

Remove one connection by index, ungating first if required.

Parameters:

Returns: Nothing.

removeFirstMatchingConnection

removeFirstMatchingConnection(
  network: default,
  candidateConnections: default[],
  sourceNode: default,
  targetNode: default,
): void

Remove first connection that matches source and target nodes.

Parameters:

Returns: Nothing.

selectConnectionCollection

selectConnectionCollection(
  network: default,
  sourceNode: default,
  targetNode: default,
): default[]

Select the relevant collection to search for the edge.

Parameters:

Returns: Candidate connection collection.

Generated from source JSDoc • GitHub