architecture/network/topology
Topology utilities.
Provides:
- computeTopoOrder: Kahn-style topological sorting with graceful fallback when cycles detected.
- hasPath: depth-first reachability query (used to prevent cycle introduction when acyclicity enforced).
- topology contract helpers: public intent accessors that keep semantic API state aligned with low-level runtime flags.
Design Notes:
- We deliberately tolerate cycles by falling back to raw node ordering instead of throwing; this allows callers performing interim structural mutations to proceed (e.g. during evolve phases) while signaling that the fast acyclic optimizations should not be used.
- Input nodes are seeded into the queue immediately regardless of in-degree to keep them early in the ordering even if an unusual inbound edge was added (defensive redundancy).
- Self loops are ignored for in-degree accounting and queue progression (they neither unlock new nodes nor should they block ordering completion).
architecture/network/topology/network.topology.utils.types.ts
ActivationSchedule
Deterministic activation schedule type used by topology helpers.
ActivationScheduleStep
Deterministic activation schedule step type used by topology helpers.
ActivationSchedulingDiagnostics
Human-friendly activation scheduling diagnostics type used by topology helpers.
IN_DEGREE_DECREMENT
Unit decrement/increment used for in-degree tally updates.
INPUT_NODE_TYPE
Input node-type discriminator used for queue seeding.
PathSearchContext
Mutable context used while running iterative DFS reachability checks.
TopologyBuildContext
Mutable context used while building Kahn topological order.
TopologyNetwork
Network instance type used by topology helpers.
TopologyNetworkProps
Internal topology state view carried across helper groups.
TopologyNode
Node instance type used by topology helpers.
ZERO_COUNT
Zero baseline used for degree counts and empty-size checks.
architecture/network/topology/network.topology.utils.ts
computeTopoOrder
computeTopoOrder(): void
Compute a deterministic activation schedule for the current topology mode.
Acyclic mode uses Kahn traversal with stable waves and still flattens those
waves back into the legacy _topoOrder cache for callers that depend on one
ordered list. Recurrent mode uses the SCC condensation graph to emit
deterministic recurrent-component boundaries while leaving the legacy acyclic
cache empty until the activation path adopts the richer schedule directly.
createMLP
createMLP(
inputCount: number,
hiddenCounts: number[],
outputCount: number,
): default
Build a strictly layered and fully connected MLP network.
Parameters:
this- Network constructor.inputCount- Number of input nodes.hiddenCounts- Hidden-layer node counts.outputCount- Number of output nodes.
Returns: Newly created MLP network.
getTopologyIntent
getTopologyIntent(): NetworkTopologyIntent
Read the public topology intent preserved on a network instance.
This accessor keeps the semantic contract visible to callers even though the lower-level runtime ultimately enforces acyclicity through booleans and cache invalidation.
Parameters:
this- Target network instance.
Returns: Current topology intent.
hasFeedForwardTopologyContract
hasFeedForwardTopologyContract(
carrier: FeedForwardTopologyContractCarrier,
): boolean
Check whether a runtime shape currently carries the feed-forward contract.
The helper is intentionally conservative when callers are in a mismatched
transitional state: either an explicit feed-forward intent or a truthy
_enforceAcyclic flag is treated as a feed-forward contract. That keeps
mutation and crossover helpers from introducing recurrent structure into a
genome that still advertises acyclic semantics anywhere on its runtime seam.
Parameters:
carrier- Narrow runtime shape or full network instance.
Returns: True when feed-forward semantics are currently enforced.
hasPath
hasPath(
from: default,
to: default,
): boolean
Depth-first reachability test (avoids infinite loops via visited set).
rebuildConnections
rebuildConnections(
networkInstance: default,
): void
Rebuild the canonical connection array from per-node outgoing lists.
Parameters:
networkInstance- Target network.
setEnforceAcyclic
setEnforceAcyclic(
flag: boolean,
): void
Toggle low-level acyclic enforcement while preserving a coherent public contract.
This exists for backward compatibility with callers that still use the legacy
boolean API instead of the semantic topologyIntent field.
Parameters:
this- Target network instance.flag- Whether to enforce acyclic connectivity.
Returns: Nothing.
setTopologyIntent
setTopologyIntent(
topologyIntent: NetworkTopologyIntent,
): void
Set the public topology intent and synchronize low-level runtime flags.
Updating the semantic contract also updates acyclic enforcement and marks the topological cache dirty so later activation paths rebuild consistent state.
Parameters:
this- Target network instance.topologyIntent- Desired topology intent.
Returns: Nothing.
architecture/network/topology/network.topology.loop.utils.ts
appendActivationStep
appendActivationStep(
activationSteps: number[][],
activationStep: number[],
): void
Append one completed activation wave to the cached schedule.
Parameters:
activationSteps- Accumulated activation waves.activationStep- Current activation wave.
Returns: Void.
appendActivationStepNode
appendActivationStepNode(
activationStep: number[],
node: default,
): void
Append one stable node id to the current activation wave.
Parameters:
activationStep- Current activation wave.node- Node to append.
Returns: Void.
appendTopoNode
appendTopoNode(
topoOrder: default[],
node: default,
): void
Append one node to topological order output.
Parameters:
topoOrder- Accumulated topological order.node- Node to append.
Returns: Void.
compareNodesByStableTieBreak
compareNodesByStableTieBreak(
leftNode: default,
rightNode: default,
): number
Compare two nodes by stable activation tie-break order.
Parameters:
leftNode- First node.rightNode- Second node.
Returns: Negative when left should run first, positive when right should run first.
decrementNodeInDegree
decrementNodeInDegree(
buildContext: TopologyBuildContext,
node: default,
): number
Decrement node in-degree and return remaining value.
Parameters:
buildContext- Mutable build context.node- Target node.
Returns: Remaining in-degree after decrement.
getInDegree
getInDegree(
buildContext: TopologyBuildContext,
node: default,
): number
Read in-degree for a node with zero fallback.
Parameters:
buildContext- Mutable build context.node- Candidate node.
Returns: In-degree value.
isInputNode
isInputNode(
node: default,
): boolean
Test whether a node is an input node.
Parameters:
node- Candidate node.
Returns: True when node type is input.
isQueueSeedNode
isQueueSeedNode(
node: default,
buildContext: TopologyBuildContext,
): boolean
Determine whether a node belongs in the initial queue.
Parameters:
node- Candidate node.buildContext- Mutable build context.
Returns: True when node is input-type or has zero in-degree.
isSelfConnection
isSelfConnection(
from: default,
to: default,
): boolean
Test whether a connection is a self-loop.
Parameters:
from- Source node.to- Target node.
Returns: True when source and target are the same node.
processKahnQueue
processKahnQueue(
buildContext: TopologyBuildContext,
): void
Process queue until all available nodes are emitted.
Parameters:
buildContext- Mutable build context.
Returns: Void.
relaxOutgoingEdges
relaxOutgoingEdges(
buildContext: TopologyBuildContext,
currentNode: default,
nextProcessingQueue: default[],
): void
Relax outgoing edges for one processed node.
Parameters:
buildContext- Mutable build context.currentNode- Processed node.
Returns: Void.
resolveStableNodeTieBreakValue
resolveStableNodeTieBreakValue(
node: default,
): number
Resolve the deterministic activation tie-break scalar for one node.
Stable gene ids are preferred. Node index remains a conservative fallback for unusual fixtures that bypass ordinary node construction.
Parameters:
node- Candidate node.
Returns: Deterministic scalar used for sorting and schedule emission.
seedProcessingQueue
seedProcessingQueue(
buildContext: TopologyBuildContext,
): void
Seed Kahn queue with input nodes and zero in-degree nodes.
Parameters:
buildContext- Mutable build context.
Returns: Void.
sortNodesByStableTieBreak
sortNodesByStableTieBreak(
nodes: default[],
): default[]
Sort one node collection by the deterministic activation tie-break.
Parameters:
nodes- Candidate nodes.
Returns: Sorted node collection.
takeNextQueueStep
takeNextQueueStep(
processingQueue: default[],
): default[]
Take the full current Kahn wave from the processing queue.
Parameters:
processingQueue- Queue of pending nodes.
Returns: Current zero-in-degree wave in deterministic order.
architecture/network/topology/network.topology.path.utils.ts
createPathSearchContext
createPathSearchContext(
from: default,
to: default,
): PathSearchContext
Create DFS search context.
Parameters:
from- Origin node.to- Target node.
Returns: Initialized path-search context.
hasVisitedNode
hasVisitedNode(
visitedNodes: Set<default>,
node: default,
): boolean
Test whether a node has already been visited.
Parameters:
visitedNodes- Visited-node set.node- Candidate node.
Returns: True when node is already visited.
isSameNode
isSameNode(
leftNode: default,
rightNode: default,
): boolean
Compare node identity.
Parameters:
leftNode- Left node.rightNode- Right node.
Returns: True when references are identical.
isSelfConnection
isSelfConnection(
from: default,
to: default,
): boolean
Test whether a connection is a self-loop.
Parameters:
from- Source node.to- Target node.
Returns: True when source and target are the same node.
markVisited
markVisited(
visitedNodes: Set<default>,
node: default,
): void
Mark a node as visited.
Parameters:
visitedNodes- Visited-node set.node- Node to mark.
Returns: Void.
pushOutgoingTargets
pushOutgoingTargets(
nodesToVisitStack: default[],
currentNode: default,
): void
Push non-self outgoing targets to DFS stack.
Parameters:
nodesToVisitStack- DFS stack.currentNode- Current expanded node.
Returns: Void.
takeNextStackNode
takeNextStackNode(
nodesToVisitStack: default[],
): default
Pop and return next DFS stack node.
Parameters:
nodesToVisitStack- DFS stack.
Returns: Next node to process.
traversePathSearch
traversePathSearch(
searchContext: PathSearchContext,
): boolean
Traverse DFS search stack and test reachability.
Parameters:
searchContext- Mutable search context.
Returns: True when target node is reachable.
architecture/network/topology/network.topology.setup.utils.ts
applyIncomingEdgeCounts
applyIncomingEdgeCounts(
buildContext: TopologyBuildContext,
): void
Apply in-degree increments from non-self connections.
Parameters:
buildContext- Mutable build context.
Returns: Void.
asTopologyProps
asTopologyProps(
network: default,
): TopologyNetworkProps
Cast network to internal topology props view.
Parameters:
network- Network instance.
Returns: Internal topology props view.
buildRecurrentScheduleSteps
buildRecurrentScheduleSteps(
stronglyConnectedComponents: readonly default[][],
condensationContext: CondensationContext,
): ActivationScheduleStep[]
Build deterministic recurrent schedule steps from the condensation graph.
Parameters:
stronglyConnectedComponents- Stable SCC list.condensationContext- Condensation graph context.
Returns: Structured recurrent schedule steps.
clearCachedTopoOrder
clearCachedTopoOrder(
internalTopologyProps: TopologyNetworkProps,
): void
Clear cached topological order state.
Parameters:
internalTopologyProps- Internal topology props view.
Returns: Void.
collectStronglyConnectedComponents
collectStronglyConnectedComponents(
nodes: readonly default[],
): default[][]
Collect strongly-connected components using Tarjan traversal.
Parameters:
nodes- Candidate graph nodes.
Returns: Stable SCC list.
createComponentIndexByNode
createComponentIndexByNode(
stronglyConnectedComponents: readonly default[][],
): Map<default, number>
Build a reverse lookup from node to SCC index.
Parameters:
stronglyConnectedComponents- Stable SCC list.
Returns: Node-to-component lookup map.
createCondensationContext
createCondensationContext(
network: default,
stronglyConnectedComponents: readonly default[][],
componentIndexByNode: ReadonlyMap<default, number>,
): CondensationContext
Build the SCC condensation graph.
Parameters:
network- Network instance.stronglyConnectedComponents- Stable SCC list.componentIndexByNode- Node-to-component lookup.
Returns: Condensation graph context.
createTopologyBuildContext
createTopologyBuildContext(
network: default,
internalTopologyProps: TopologyNetworkProps,
): TopologyBuildContext
Create mutable build context for Kahn traversal.
Parameters:
network- Network instance.internalTopologyProps- Internal topology props view.
Returns: Initialized build context.
finalizeRecurrentSchedule
finalizeRecurrentSchedule(
network: default,
internalTopologyProps: TopologyNetworkProps,
): void
Build and cache the deterministic recurrent schedule.
Parameters:
network- Network instance.internalTopologyProps- Internal topology props view.
Returns: Void.
finalizeTopoOrder
finalizeTopoOrder(
buildContext: TopologyBuildContext,
): void
Finalize cached order, falling back to raw node order on cycle detection.
Parameters:
buildContext- Mutable build context.
Returns: Void.
incrementNodeInDegree
incrementNodeInDegree(
buildContext: TopologyBuildContext,
node: default,
): void
Increment in-degree for a node in the tally map.
Parameters:
buildContext- Mutable build context.node- Target node.
Returns: Void.
initializeAllNodeInDegreeCounts
initializeAllNodeInDegreeCounts(
buildContext: TopologyBuildContext,
): void
Initialize all nodes with zero in-degree.
Parameters:
buildContext- Mutable build context.
Returns: Void.
isRecurrentComponent
isRecurrentComponent(
componentNodes: readonly default[],
): boolean
Check whether one SCC should be treated as a recurrent execution boundary.
Parameters:
componentNodes- Stable SCC node list.
Returns: True when the component is cyclic or carries a self-loop.
isSelfConnection
isSelfConnection(
from: default,
to: default,
): boolean
Test whether a connection is a self-loop.
Parameters:
from- Source node.to- Target node.
Returns: True when source and target are the same node.
resolveCompiledSchedulingDiagnostics
resolveCompiledSchedulingDiagnostics(
network: default,
activationSchedule: ActivationSchedule,
): ActivationSchedulingDiagnostics
Resolve the standard diagnostics payload for a compiled schedule.
Parameters:
network- Network instance.activationSchedule- Compiled activation schedule.
Returns: Scheduling diagnostics snapshot.
resolveComponentTieBreakValue
resolveComponentTieBreakValue(
componentNodes: readonly default[],
): number
Resolve one SCC tie-break value from its first stable node.
Parameters:
componentNodes- Stable SCC node list.
Returns: Deterministic component sort scalar.
resolveCycleNodeIds
resolveCycleNodeIds(
buildContext: TopologyBuildContext,
): number[]
Resolve stable node ids that remained unscheduled after acyclic traversal.
Parameters:
buildContext- Mutable build context.
Returns: Stable node ids implicated in the cycle fallback.
resolveFinalActivationSchedule
resolveFinalActivationSchedule(
buildContext: TopologyBuildContext,
): ActivationSchedule | null
Resolve the final deterministic activation schedule when the graph is acyclic.
Parameters:
buildContext- Mutable build context.
Returns: Cached activation schedule or null when a complete acyclic order was not found.
resolveFinalOrder
resolveFinalOrder(
buildContext: TopologyBuildContext,
): default[]
Resolve final topological order with cycle fallback.
Parameters:
buildContext- Mutable build context.
Returns: Fully valid topological order or raw node order fallback.
resolveFinalSchedulingDiagnostics
resolveFinalSchedulingDiagnostics(
buildContext: TopologyBuildContext,
): ActivationSchedulingDiagnostics
Resolve final human-friendly scheduling diagnostics for acyclic mode.
Parameters:
buildContext- Mutable build context.
Returns: Scheduling diagnostics snapshot.
resolveOutgoingNeighbors
resolveOutgoingNeighbors(
node: default,
): default[]
Resolve one node's outgoing neighbors for SCC traversal.
Self-loops are excluded from traversal because they do not change SCC membership, but singleton self-loops are still classified as recurrent later.
Parameters:
node- Candidate node.
Returns: Deterministic outgoing neighbors.
resolveRecurrentActivationSchedule
resolveRecurrentActivationSchedule(
network: default,
): ActivationSchedule
Resolve the deterministic recurrent activation schedule.
The schedule is based on the SCC condensation graph so recurrent structure is explicit before activation-path integration consumes it.
Parameters:
network- Network instance.
Returns: Deterministic recurrent activation schedule.
seedCondensationQueue
seedCondensationQueue(
stronglyConnectedComponents: readonly default[][],
componentInDegree: readonly number[],
queuedComponentIndexes: Set<number>,
): number[]
Seed the condensation queue with zero-indegree or input-owning components.
Parameters:
stronglyConnectedComponents- Stable SCC list.componentInDegree- Component indegree counts.queuedComponentIndexes- Mutable set of already queued components.
Returns: Initial deterministic queue.
shouldBuildRecurrentSchedule
shouldBuildRecurrentSchedule(
internalTopologyProps: TopologyNetworkProps,
): boolean
Determine whether recurrent scheduling should be used.
Parameters:
internalTopologyProps- Internal topology props view.
Returns: True when acyclic mode is disabled.
sortComponentIndexesByTieBreak
sortComponentIndexesByTieBreak(
componentIndexes: readonly number[],
stronglyConnectedComponents: readonly default[][],
): number[]
Sort component indexes by the deterministic node tie-break of each SCC root.
Parameters:
componentIndexes- Candidate component indexes.stronglyConnectedComponents- Stable SCC list.
Returns: Sorted component indexes.
architecture/network/topology/network.topology.factory.utils.ts
addOutgoingConnectionsToSet
addOutgoingConnectionsToSet(
outgoingConnections: default[],
allConnections: Set<default>,
): void
Add all outgoing connections to a deduplication set.
Parameters:
outgoingConnections- Outgoing connections from one node.allConnections- Deduplication set for network connections.
assignNetworkNodes
assignNetworkNodes(
networkInstance: default,
mlpNodeLayers: MlpNodeLayers,
): void
Assign ordered nodes to the network instance.
Parameters:
networkInstance- Target network.mlpNodeLayers- Grouped node layers for this MLP.
collectUniqueOutgoingConnections
collectUniqueOutgoingConnections(
networkInstance: default,
): Set<default>
Collect unique outgoing connections across all network nodes.
Parameters:
networkInstance- Target network.
Returns: Set of unique outgoing connections.
connectLayerPair
connectLayerPair(
sourceLayer: default[],
targetLayer: default[],
): void
Fully connect every source node to every target node.
Parameters:
sourceLayer- Source layer.targetLayer- Target layer.
connectMlpLayers
connectMlpLayers(
mlpNodeLayers: MlpNodeLayers,
): void
Fully connect each adjacent layer in MLP order.
Parameters:
mlpNodeLayers- Grouped node layers for this MLP.
convertConnectionSetToArray
convertConnectionSetToArray(
uniqueConnections: Set<default>,
): default[]
Convert a connection set into the canonical array format.
Parameters:
uniqueConnections- Unique network connections.
Returns: Array of network connections.
createHiddenLayers
createHiddenLayers(
hiddenCounts: number[],
): default[][]
Create all hidden layers for an MLP topology.
Parameters:
hiddenCounts- Hidden-layer node counts.
Returns: Hidden layers in forward order.
createMLP
createMLP(
inputCount: number,
hiddenCounts: number[],
outputCount: number,
): default
Build a strictly layered and fully connected MLP network.
Parameters:
this- Network constructor.inputCount- Number of input nodes.hiddenCounts- Hidden-layer node counts.outputCount- Number of output nodes.
Returns: Newly created MLP network.
createMlpNodeLayers
createMlpNodeLayers(
inputCount: number,
hiddenCounts: number[],
outputCount: number,
): MlpNodeLayers
Build input, hidden, and output node layers for an MLP topology.
Parameters:
inputCount- Number of input nodes.hiddenCounts- Hidden-layer node counts.outputCount- Number of output nodes.
Returns: Grouped node layers for MLP assembly.
createNodesOfType
createNodesOfType(
nodeCount: number,
nodeType: "hidden" | "input" | "output",
): default[]
Create all nodes for a single fixed node type.
Parameters:
nodeCount- Number of nodes to create.nodeType- Node type identifier.
Returns: Node list of the requested type.
createOrderedNodeList
createOrderedNodeList(
mlpNodeLayers: MlpNodeLayers,
): default[]
Build the canonical ordered node list used by the network.
Parameters:
mlpNodeLayers- Grouped node layers for this MLP.
Returns: Ordered node list: input, hidden, then output.
flattenNodeLayers
flattenNodeLayers(
nodeLayers: default[][],
): default[]
Flatten layered node collections into a single ordered list.
Parameters:
nodeLayers- Layered node collections.
Returns: Flattened node list.
instantiateNetwork
instantiateNetwork(
networkFactory: NetworkConstructor,
inputCount: number,
outputCount: number,
): default
Instantiate a new network using the runtime constructor.
Parameters:
networkFactory- Network constructor function.inputCount- Number of input nodes.outputCount- Number of output nodes.
Returns: Newly instantiated network.
markTopologyDirty
markTopologyDirty(
networkInstance: default,
): void
Mark a network topology as dirty after structural edits.
Parameters:
networkInstance- Network instance to mark.
rebuildConnections
rebuildConnections(
networkInstance: default,
): void
Rebuild the canonical connection array from per-node outgoing lists.
Parameters:
networkInstance- Target network.
architecture/network/topology/network.topology.contract.utils.ts
FeedForwardTopologyContractCarrier
Minimal runtime surface needed to read the active feed-forward contract.
Some callers have a full Network instance with getTopologyIntent(), while
others only hold a narrow runtime genome shape with the low-level acyclic flag.
This contract keeps both shapes usable from one small helper.
getTopologyIntent
getTopologyIntent(): NetworkTopologyIntent
Read the public topology intent preserved on a network instance.
This accessor keeps the semantic contract visible to callers even though the lower-level runtime ultimately enforces acyclicity through booleans and cache invalidation.
Parameters:
this- Target network instance.
Returns: Current topology intent.
hasFeedForwardTopologyContract
hasFeedForwardTopologyContract(
carrier: FeedForwardTopologyContractCarrier,
): boolean
Check whether a runtime shape currently carries the feed-forward contract.
The helper is intentionally conservative when callers are in a mismatched
transitional state: either an explicit feed-forward intent or a truthy
_enforceAcyclic flag is treated as a feed-forward contract. That keeps
mutation and crossover helpers from introducing recurrent structure into a
genome that still advertises acyclic semantics anywhere on its runtime seam.
Parameters:
carrier- Narrow runtime shape or full network instance.
Returns: True when feed-forward semantics are currently enforced.
setEnforceAcyclic
setEnforceAcyclic(
flag: boolean,
): void
Toggle low-level acyclic enforcement while preserving a coherent public contract.
This exists for backward compatibility with callers that still use the legacy
boolean API instead of the semantic topologyIntent field.
Parameters:
this- Target network instance.flag- Whether to enforce acyclic connectivity.
Returns: Nothing.
setTopologyIntent
setTopologyIntent(
topologyIntent: NetworkTopologyIntent,
): void
Set the public topology intent and synchronize low-level runtime flags.
Updating the semantic contract also updates acyclic enforcement and marks the topological cache dirty so later activation paths rebuild consistent state.
Parameters:
this- Target network instance.topologyIntent- Desired topology intent.
Returns: Nothing.
architecture/network/topology/network.topology.architecture.utils.ts
createArchitectureDescriptor
createArchitectureDescriptor(
hiddenLayerSizes: number[],
hasCycles: boolean,
source: NetworkArchitectureSource,
totalNodes: number,
totalConnections: number,
): NetworkArchitectureDescriptor
Creates the final immutable descriptor shape used by telemetry and UI code.
Keeping descriptor assembly in one place ensures every resolution strategy returns the same payload contract and avoids accidental field drift.
Parameters:
hiddenLayerSizes- Hidden-layer widths.hasCycles- Whether cycles were detected.source- Descriptor provenance.totalNodes- Node count.totalConnections- Connection count.
Returns: Descriptor object.
Example:
const descriptor = createArchitectureDescriptor([6, 3], false, 'graph-topology', 14, 25);
// descriptor.totalNodes === 14
createDirectedEdgeList
createDirectedEdgeList(
runtimeConnections: RuntimeConnectionLike[],
nodeByIndex: Map<number, RuntimeNodeLike>,
): { fromIndex: number; toIndex: number; }[]
Produces a validated list of enabled directed edges.
Invalid references, disabled connections, and self-loops are removed so the remaining edge list can be consumed safely by cycle and depth algorithms.
Parameters:
runtimeConnections- Runtime connections.nodeByIndex- Indexed nodes.
Returns: Valid directed edges.
Example:
const edges = createDirectedEdgeList(runtimeConnections, nodeByIndex);
// edges -> [{ fromIndex: 0, toIndex: 3 }, ...]
createNodeIndexMap
createNodeIndexMap(
runtimeNodes: RuntimeNodeLike[],
): Map<number, RuntimeNodeLike>
Builds a node lookup table keyed by stable index.
Runtime objects may omit index; in that case the current array position is
used as a deterministic fallback to keep downstream graph logic total.
Parameters:
runtimeNodes- Runtime nodes.
Returns: Node map keyed by stable node index.
Example:
const nodeByIndex = createNodeIndexMap(nodes);
// nodeByIndex.get(0) -> first node or node with explicit index 0
describeArchitecture
describeArchitecture(
network: default,
): NetworkArchitectureDescriptor
Describes network architecture for diagnostics, telemetry, and UI rendering.
This function prefers factual sources over heuristics so downstream tooling can rely on the descriptor while still receiving useful output for partially specified runtime graphs.
Resolution priority is intentionally explicit:
- node
layermetadata (factual when present) - graph-derived feed-forward depth layering (factual for acyclic graphs)
- hidden-node count fallback (heuristic inference)
Parameters:
network- Runtime network instance.
Returns: Stable architecture descriptor.
Example:
const descriptor = describeArchitecture(network);
// descriptor.hiddenLayerSizes -> [8, 4]
// descriptor.source -> 'layer-metadata' | 'graph-topology' | 'inferred'
isHiddenNode
isHiddenNode(
runtimeNode: RuntimeNodeLike,
): boolean
Identifies whether a runtime node should be treated as hidden for topology reconstruction and fallback inference.
Parameters:
runtimeNode- Candidate node.
Returns: True when node type is hidden.
Example:
if (isHiddenNode(node)) {
// Include in hidden-layer counting
}
isHydratedDescriptorCompatible
isHydratedDescriptorCompatible(
network: default,
hydratedDescriptor: NetworkArchitectureDescriptor | undefined,
): boolean
Check whether hydrated descriptor metadata still matches the current graph shape.
Parameters:
network- Runtime network instance.hydratedDescriptor- Optional hydrated descriptor candidate.
Returns: True when hydrated descriptor can safely stand in for the inferred result.
resolveArchitectureDescriptor
resolveArchitectureDescriptor(
network: default,
): NetworkArchitectureDescriptor
Resolve the public architecture descriptor, preferring live graph facts and falling back to hydrated serialization metadata only when the live result is still purely inferred.
This helper keeps the descriptor ownership story in one chapter: topology owns the live analysis while serialization can optionally hydrate a cached descriptor that remains safe to reuse when the runtime graph shape matches.
Parameters:
network- Runtime network instance.
Returns: Public architecture descriptor for telemetry and UI consumers.
resolveCycleStateAndTopoOrder
resolveCycleStateAndTopoOrder(
nodeByIndex: Map<number, RuntimeNodeLike>,
directedEdges: { fromIndex: number; toIndex: number; }[],
): { topologicalOrder: number[]; hasCycles: boolean; }
Resolves cycle presence and, when possible, returns a topological order using Kahn's algorithm.
A complete topological ordering implies an acyclic graph. If some nodes remain unprocessed, at least one cycle exists.
Parameters:
nodeByIndex- Indexed nodes.directedEdges- Directed edges.
Returns: Topological order and cycle status.
Example:
const { topologicalOrder, hasCycles } = resolveCycleStateAndTopoOrder(nodeByIndex, edges);
resolveHiddenCountsByDepth
resolveHiddenCountsByDepth(
nodeByIndex: Map<number, RuntimeNodeLike>,
depthByNodeIndex: Map<number, number>,
): Map<number, number>
Aggregates hidden-node counts per derived depth.
This is the final transformation before emitting architecture widths: hidden nodes are grouped by depth and counted in insertion-safe maps.
Parameters:
nodeByIndex- Indexed nodes.depthByNodeIndex- Derived depths.
Returns: Hidden-node counts by depth.
Example:
const hiddenCountsByDepth = resolveHiddenCountsByDepth(nodeByIndex, depthByNodeIndex);
resolveHiddenLayerSizesFromGraphTopology
resolveHiddenLayerSizesFromGraphTopology(
runtimeNodes: RuntimeNodeLike[],
runtimeConnections: RuntimeConnectionLike[],
): { hiddenLayerSizes: number[]; hasCycles: boolean; }
Derives hidden-layer widths from graph topology when no explicit layer metadata is available.
The method computes a topological depth model for acyclic graphs; cyclic graphs are flagged and intentionally return no width inference because depth is not well-defined in recurrent loops.
Parameters:
runtimeNodes- Runtime nodes.runtimeConnections- Runtime connections.
Returns: Hidden-layer widths derived from acyclic topology and cycle flag.
Example:
const { hiddenLayerSizes, hasCycles } = resolveHiddenLayerSizesFromGraphTopology(nodes, edges);
resolveHiddenLayerSizesFromLayerMetadata
resolveHiddenLayerSizesFromLayerMetadata(
runtimeNodes: RuntimeNodeLike[],
): number[]
Resolves hidden-layer widths from explicit node.layer metadata.
This is treated as the most trustworthy source because layer assignment is usually produced by architecture-aware builders and does not depend on topological reconstruction.
Parameters:
runtimeNodes- Runtime nodes.
Returns: Hidden-layer widths from explicit node.layer metadata.
Example:
// Hidden nodes in layers 1, 1, and 2 -> [2, 1]
const sizes = resolveHiddenLayerSizesFromLayerMetadata(nodes);
resolveNodeDepthByIndex
resolveNodeDepthByIndex(
nodeByIndex: Map<number, RuntimeNodeLike>,
directedEdges: { fromIndex: number; toIndex: number; }[],
topologicalOrder: number[],
): Map<number, number>
Computes node depth (feed-forward distance from inputs) for an acyclic graph.
Depth assignment is parent-driven: each node depth is one plus the maximum resolved parent depth. Nodes with no resolved parents are skipped.
Parameters:
nodeByIndex- Indexed nodes.directedEdges- Directed edges.topologicalOrder- Acyclic topological order.
Returns: Derived depth by node index.
Example:
const depthByNodeIndex = resolveNodeDepthByIndex(nodeByIndex, edges, topologicalOrder);