import { RectDiffPipeline } from '@tscircuit/rectdiff'; import { ConnectivityMap } from 'circuit-json-to-connectivity-map'; import * as graphics_debug from 'graphics-debug'; import { GraphicsObject, Rect, Circle, Line, Point as Point$5 } from 'graphics-debug'; import { BaseSolver as BaseSolver$1, BasePipelineSolver, PipelineStep as PipelineStep$a } from '@tscircuit/solver-utils'; import { HighDensitySolverA03, NodeWithPortPoints as NodeWithPortPoints$1 } from '@tscircuit/high-density-a01'; import Flatbush from 'flatbush'; import { Point3, Polygon } from '@tscircuit/math-utils'; import { CurvyTraceSolver } from '@tscircuit/curvy-trace-solver'; import { JumperGraphSolver, JRegion, JPort, HyperGraph, RegionPort, Region, RegionPortAssignment, Connection, SolvedRoute, Candidate as Candidate$3, HyperGraphSolver, HyperGraphSectionOptimizer } from '@tscircuit/hypergraph'; import { ConnectivityMap as ConnectivityMap$1 } from 'connectivity-map'; import { HighDensityForceImproveSolver } from 'high-density-repair01/lib/HighDensityForceImproveSolver'; import { GlobalDrcForceImproveSolver } from 'high-density-repair03/lib'; export { DrcError, DrcEvaluator, DrcSnapshot, GlobalDrcForceImproveSolver, GlobalDrcForceImproveSolverParams, HighDensityRoute, SimpleRouteJson, SimplifiedPcbTrace } from 'high-density-repair03/lib'; import { DatasetSample, HighDensityRepairSolver } from 'high-density-repair02'; import { LayerMergeMode, ConvexRegionsComputeResult, SerializedPolyHyperGraph } from 'pcb-poly-hyper-graph'; import { PolyHyperGraphLoadResult, PolyHyperGraphSolver } from 'tiny-hypergraph-poly/lib/index'; interface CacheProvider { isSyncCache: boolean; cacheHits: number; cacheMisses: number; cacheHitsByPrefix: Record; cacheMissesByPrefix: Record; getCachedSolutionSync(cacheKey: string): any; getCachedSolution(cacheKey: string): Promise; setCachedSolutionSync(cacheKey: string, cachedSolution: any): void; setCachedSolution(cacheKey: string, cachedSolution: any): Promise; getAllCacheKeys(): string[]; clearCache(): void; } interface CachableSolver { cacheHit: boolean; hasAttemptedToUseCache: boolean; cacheProvider: CacheProvider | null; cacheKey?: string; cacheToSolveSpaceTransform?: CacheToSolveSpaceTransform; /** * Processes solver inputs and constructs a cacheKey and a cacheToSolveSpaceTransform * which gives the necessary information to convert a cached solution into a valid * solution for this solver. For example, the cacheKey may be translation-invariant, so * any cachedSolution would not be translated properly for this solver. The cacheToSolveSpaceTransform * tells you how to convert from the cache space (translation-invarant) to the correct * space for this solver. It can also contain information about how cache ids map to * ids for the solver **/ computeCacheKeyAndTransform(): { cacheKey: string; cacheToSolveSpaceTransform: CacheToSolveSpaceTransform; }; applyCachedSolution(cachedSolution: CachedSolution): void; attemptToUseCacheSync(): boolean; saveToCacheSync(): void; } type TraceId = string; type NetId = string; type BusId = string; type PointId = string; type OffBoardConnectionId = string; type ObstacleId = string; type RootConnectionName = string; type TerminalViaHint = { toLayer: string; viaDiameter?: number; }; type SingleLayerConnectionPoint = { x: number; y: number; layer: string; pointId?: PointId; pcb_port_id?: string; terminalVia?: TerminalViaHint; }; type MultiLayerConnectionPoint = { x: number; y: number; layers: string[]; pointId?: PointId; busId?: BusId; pcb_port_id?: string; }; type ConnectionPoint$1 = SingleLayerConnectionPoint | MultiLayerConnectionPoint; type Jumper$1 = { jumper_footprint: "0603" | "1206x4"; center: { x: number; y: number; }; orientation: "horizontal" | "vertical"; width: number; height: number; pads: Obstacle[]; }; type JumperType = "1206x4" | "0603"; interface SimpleRouteJson { layerCount: number; minTraceWidth: number; nominalTraceWidth?: number; /** @deprecated Use `min_via_pad_diameter` / `minViaPadDiameter` instead. */ minViaDiameter?: number; minViaHoleDiameter?: number; minViaPadDiameter?: number; min_via_hole_diameter?: number; min_via_pad_diameter?: number; defaultObstacleMargin?: number; minTraceToPadEdgeClearance?: number; obstacles: Obstacle[]; connections: Array; bounds: { minX: number; maxX: number; minY: number; maxY: number; }; outline?: Array<{ x: number; y: number; }>; traces?: SimplifiedPcbTraces; jumpers?: Jumper$1[]; allowJumpers?: boolean; /** Available jumper types for routing. Defaults to ["0603"] */ availableJumperTypes?: JumperType[]; } interface Obstacle { obstacleId?: string; /** Optional source component identifier associated with this obstacle. */ componentId?: string; type: "rect"; layers: string[]; zLayers?: number[]; center: { x: number; y: number; }; width: number; height: number; /** Optional counter-clockwise rotation metadata in degrees. */ ccwRotationDegrees?: number; connectedTo: Array; isCopperPour?: boolean; netIsAssignable?: boolean; offBoardConnectsTo?: Array; } interface SimpleRouteConnection { name: string; rootConnectionName?: string; mergedConnectionNames?: string[]; isOffBoard?: boolean; netConnectionName?: string; nominalTraceWidth?: number; pointsToConnect: Array; /** @deprecated DO NOT USE **/ externallyConnectedPointIds?: PointId[][]; } interface SimplifiedPcbTrace { type: "pcb_trace"; pcb_trace_id: TraceId; connection_name: string; route: Array<{ route_type: "wire"; x: number; y: number; width: number; layer: string; } | { route_type: "via"; x: number; y: number; to_layer: string; from_layer: string; via_diameter?: number; via_hole_diameter?: number; } | { route_type: "jumper"; /** Starting point of the jumper pad */ start: { x: number; y: number; }; /** Ending point of the jumper pad */ end: { x: number; y: number; }; /** Footprint size, typically "0603" */ footprint: "0603" | "1206" | "1206x4_pair"; layer: string; } | { route_type: "through_obstacle"; start: { x: number; y: number; }; end: { x: number; y: number; }; from_layer: string; to_layer: string; width: number; }>; } type SimplifiedPcbTraces = Array; type CapacityMeshNodeId = string; interface CapacityMeshNode { capacityMeshNodeId: string; center: { x: number; y: number; }; width: number; height: number; layer: string; availableZ: number[]; _depth?: number; _completelyInsideObstacle?: boolean; _containsObstacle?: boolean; _containsTarget?: boolean; _targetConnectionName?: string; _strawNode?: boolean; _strawParentCapacityMeshNodeId?: CapacityMeshNodeId; _isVirtualOffboard?: boolean; _offboardNetName?: string; _adjacentNodeIds?: CapacityMeshNodeId[]; _offBoardConnectionId?: string; _offBoardConnectedCapacityMeshNodeIds?: CapacityMeshNodeId[]; _qfpRegionType?: "center" | "pad" | "pad-gap" | "corner"; _isNarrowQfpPadGap?: boolean; _soicRegionType?: "center" | "pad" | "pad-gap"; _parent?: CapacityMeshNode; } interface CapacityMeshEdge { capacityMeshEdgeId: string; nodeIds: [CapacityMeshNodeId, CapacityMeshNodeId]; isOffboardEdge?: boolean; offboardNetName?: string; } type CapacityPathId = string; interface CapacityPath { capacityPathId: CapacityPathId; connectionName: string; rootConnectionName?: string; nodeIds: CapacityMeshNodeId[]; /** True if this path was created by splitting at an offboard edge */ isFragmentedPath?: boolean; /** MST pair connection name before fragmentation */ mstPairConnectionName?: string; } type PortPoint = { connectionName: string; rootConnectionName?: string; portPointId?: string; x: number; y: number; z: number; prevPortPointId?: string; nextPortPointId?: string; }; type NodeWithPortPoints = { capacityMeshNodeId: string; center: { x: number; y: number; }; width: number; height: number; portPoints: PortPoint[]; availableZ?: number[]; portPointsInPairs?: [PortPoint, PortPoint][]; }; /** * A path for a wire in high-density intra-node routing. * * Wires travel along a route, and are placed to avoid other * wires at the same z-level. Any time a z level is changed, * you must place a via. * * z is an integer corresponding to the layer index * * z=0: top layer for 2 layer boards * z=1: bottom layer for 2 layer boards * * z must be an integer */ type HighDensityIntraNodeRoute$1 = { connectionName: string; rootConnectionName?: string; traceThickness: number; viaDiameter: number; route: Array<{ x: number; y: number; z: number; traceThickness?: number; insideJumperPad?: boolean; toNextSegmentType?: "through_obstacle"; }>; vias: Array<{ x: number; y: number; }>; jumpers?: Jumper[]; regionId?: string; }; type HighDensityRoute$1 = HighDensityIntraNodeRoute$1; /** * A jumper component used to allow traces to cross on single-layer PCBs. * - "0603": Single 0603 jumper * - "1206": Single 1206 jumper * - "1206x4_pair": One of 4 internal jumper pairs in a 1206x4 resistor array */ type Jumper = { route_type: "jumper"; /** Starting point of the jumper */ start: { x: number; y: number; }; /** Ending point of the jumper */ end: { x: number; y: number; }; /** Footprint size */ footprint: "0603" | "1206" | "1206x4_pair"; }; /** * An intra-node route that uses jumpers instead of vias for single-layer PCBs. */ type HighDensityIntraNodeRouteWithJumpers = { connectionName: string; rootConnectionName?: string; regionId?: string; traceThickness: number; route: Array<{ x: number; y: number; z: number; }>; jumpers: Jumper[]; }; type PendingEffect = { name: string; promise: Promise; }; declare class BaseSolver { MAX_ITERATIONS: number; solved: boolean; failed: boolean; iterations: number; progress: number; error: string | null; activeSubSolver?: BaseSolver | null; failedSubSolvers?: BaseSolver[]; timeToSolve?: number; stats: Record; pendingEffects?: PendingEffect[]; /** * For cached solvers **/ cacheHit?: boolean; cacheKey?: string; cacheToSolveSpaceTransform?: any; getSolverName(): string; /** DO NOT OVERRIDE! Override _step() instead */ step(): void; _step(): void; getConstructorParams(): void; solve(): void; visualize(): GraphicsObject; /** * Called when the solver is about to fail, but we want to see if we have an * "acceptable" or "passable" solution. Mostly used for optimizers that * have an aggressive early stopping criterion. */ tryFinalAcceptance(): void; /** * A lightweight version of the visualize method that can be used to stream * progress */ preview(): GraphicsObject; } /** * Precomputed parameters that can be shared across multiple PortPointPathingSolver instances. * These are computed once and passed to each solver to avoid redundant computation. */ interface PrecomputedInitialParams { /** Map from nodeId to InputNodeWithPortPoints */ nodeMap: Map; /** Average node pitch for heuristic calculations */ avgNodePitch: number; /** Nodes with off-board connections */ offBoardNodes: InputNodeWithPortPoints[]; /** Map from portPointId to InputPortPoint */ portPointMap: Map; /** Map from nodeId to list of port points accessible from that node */ nodePortPointsMap: Map; /** Map from nodeId to assigned port points (empty initially, will be cloned per solver) */ nodeAssignedPortPoints: Map; /** Connections with results (NOT shuffled) - shuffling is done per solver */ unshuffledConnectionsWithResults: ConnectionPathResult[]; /** Map from connection name to goal node IDs */ connectionNameToGoalNodeIds: Map; } interface PortPointPathingHyperParameters { SHUFFLE_SEED?: number; CENTER_OFFSET_DIST_PENALTY_FACTOR?: number; CENTER_OFFSET_FOCUS_SHIFT?: number; GREEDY_MULTIPLIER?: number; NODE_PF_FACTOR?: number; RANDOM_COST_MAGNITUDE?: number; NODE_PF_MAX_PENALTY?: number; MEMORY_PF_FACTOR?: number; BASE_CANDIDATE_COST?: number; MIN_ALLOWED_BOARD_SCORE?: number; MAX_ITERATIONS_PER_PATH?: number; FORCE_CENTER_FIRST?: boolean; RANDOM_WALK_DISTANCE?: number; FORCE_OFF_BOARD_FREQUENCY?: number; FORCE_OFF_BOARD_SEED?: number; RIPPING_ENABLED?: boolean; RIPPING_PF_THRESHOLD?: number; START_RIPPING_PF_THRESHOLD?: number; END_RIPPING_PF_THRESHOLD?: number; MAX_RIPS?: number; RANDOM_RIP_FRACTION?: number; /** When enabled, use jumper-based pf calculation for same-layer crossings on single layer nodes */ JUMPER_PF_FN_ENABLED?: boolean; /** Factor for penalizing deviation from straight line path */ STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR?: number; } /** * An input port point without connectionName assigned yet. * These are pre-computed points on node edges where traces can cross. */ interface InputPortPoint { portPointId: string; x: number; y: number; z: number; prevPortPointId?: string; nextPortPointId?: string; /** The node IDs that this port point connects (on the shared edge) */ connectionNodeIds: [CapacityMeshNodeId, CapacityMeshNodeId]; /** XY distance to the centermost port on this Z level (centermost port has distance 0) */ distToCentermostPortOnZ: number; cramped?: boolean; connectsToOffBoardNode?: boolean; } /** * A node with pre-computed port points (without connectionName assigned). * This is the input format for PortPointPathingSolver. */ interface InputNodeWithPortPoints { capacityMeshNodeId: CapacityMeshNodeId; center: { x: number; y: number; }; width: number; height: number; /** Port points on this node's edges (without connectionName) */ portPoints: InputPortPoint[]; availableZ: number[]; /** If true, this node is a target node (contains a connection endpoint) */ _containsTarget?: boolean; /** If true, this node contains an obstacle */ _containsObstacle?: boolean; _offBoardConnectionId?: string; _offBoardConnectedCapacityMeshNodeIds?: CapacityMeshNodeId[]; _qfpRegionType?: "center" | "pad" | "pad-gap" | "corner"; _isNarrowQfpPadGap?: boolean; } /** * A candidate in the A* search. Represents being at a port point, * having entered from a specific node. */ interface PortPointCandidate { prevCandidate: PortPointCandidate | null; /** The port point we're at (null for start/end target points) */ portPoint: InputPortPoint | null; /** The node we're currently in (entered via portPoint) */ currentNodeId: CapacityMeshNodeId; /** The physical point location (entry point within currentNodeId) */ point: { x: number; y: number; }; /** The z layer this candidate is on */ z: number; f: number; g: number; h: number; /** Total distance traveled from start to this candidate */ distanceTraveled: number; /** Whether this candidate has ever crossed through an off-board node */ hasTouchedOffBoardNode?: boolean; lastMoveWasOffBoard?: boolean; /** The node we went through when making an off-board move */ throughNodeId?: CapacityMeshNodeId; } interface ConnectionPathResult { connection: SimpleRouteConnection; /** Start and end node IDs */ nodeIds: [CapacityMeshNodeId, CapacityMeshNodeId]; /** The path of candidates found by the pathing algorithm */ path?: PortPointCandidate[]; /** Port points used by this connection (with connectionName assigned) */ portPoints?: PortPoint[]; straightLineDistance: number; } /** * PortPointPathingSolver finds paths through the capacity mesh by visiting * pre-computed port points on shared edges. It considers layer information * when routing and uses a Pf-based cost function. * * Improvements in this implementation: * - g is now an *exact* accumulated path cost (incremental delta Pf per node, computed only when a node is "closed") * - node Pf contribution is charged when you *leave* a node (entry+exit known), not when entering the next node * - uses a log-success style cost: cost(pf) = -log(1 - pf), and delta = cost(after) - cost(before) * - caches base node costs and segment delta costs to avoid repeated crossing computations * - computeH uses memoryPf + distance to approximate remaining cost (and can be tuned) * - closes the end node when connecting to the final end target point * - prevents node cycles in a candidate chain (keeps Pf math correct without needing per-node multi-visit tracking) */ declare class PortPointPathingSolver extends BaseSolver { input: { simpleRouteJson: SimpleRouteJson; capacityMeshNodes: CapacityMeshNode[]; inputNodes: InputNodeWithPortPoints[]; colorMap?: Record; nodeMemoryPfMap?: Map; hyperParameters?: Partial; precomputedInitialParams?: PrecomputedInitialParams; /** Pre-routed connections that should not be re-routed but should appear in results */ fixedRoutes?: ConnectionPathResult[]; }; getSolverName(): string; hyperParameters: Partial; simpleRouteJson: SimpleRouteJson; inputNodes: InputNodeWithPortPoints[]; nodeMap: Map; /** Map from nodeId to list of port points accessible from that node */ nodePortPointsMap: Map; /** Map from portPointId to InputPortPoint */ portPointMap: Map; connectionsWithResults: ConnectionPathResult[]; failedConnection: ConnectionPathResult | null; /** Tracks port points that have been assigned to connections */ assignedPortPoints: Map; /** Tracks port points assigned to each node for crossing calculations */ nodeAssignedPortPoints: Map; /** Factor applied to port point reuse penalty */ PORT_POINT_REUSE_FACTOR: number; /** * Cost when a node doesn't go off board when it's supposed to w/ the * FORCE_OFF_BOARD_FREQUENCY setting. */ BASE_COST_FOR_NOT_GOING_OFF_BOARD: number; /** Multiplied by Pf delta cost (in -log(1-pf) space) */ get NODE_PF_FACTOR(): number; get RANDOM_WALK_DISTANCE(): number; /** Used only in heuristic (h) to "look ahead" into known-congested regions */ get MEMORY_PF_FACTOR(): number; get CENTER_OFFSET_FOCUS_SHIFT(): number; /** Used as a *tie-breaker* in f (not part of g) */ get RANDOM_COST_MAGNITUDE(): number; /** Cost of adding a candidate to the path */ get BASE_CANDIDATE_COST(): number; get NODE_PF_MAX_PENALTY(): number; get FORCE_CENTER_FIRST(): boolean; get FORCE_OFF_BOARD_FREQUENCY(): number; get FORCE_OFF_BOARD_SEED(): number; get NODE_MAX_PF(): number; /** Penalty factor for port points that are far from the center of the segment */ get CENTER_OFFSET_DIST_PENALTY_FACTOR(): number; get STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR(): number; colorMap: Record; get GREEDY_MULTIPLIER(): number; MAX_CANDIDATES_IN_MEMORY: number; get MAX_ITERATIONS_PER_PATH(): number; ITERATIONS_PER_MM_FOR_PATH: number; BASE_ITERATIONS_PER_PATH: number; get RIPPING_ENABLED(): boolean; get RIPPING_PF_THRESHOLD(): number; get MAX_RIPS(): number; get RANDOM_RIP_FRACTION(): number; get JUMPER_PF_FN_ENABLED(): boolean; /** Number of jumpers that can fit per mm² of node area */ jumpersPerMmSquared: number; /** Tracks which connections have been test-ripped for each node to avoid retesting */ testedRipConnections: Map>; /** Tracks total number of connections that have been ripped/requeued */ totalRipCount: number; get MIN_ALLOWED_BOARD_SCORE(): number; nodeMemoryPfMap: Map; /** Connections waiting to be routed */ unprocessedConnectionQueue: ConnectionPathResult[]; /** Connections that have been successfully routed */ processedConnectionQueue: ConnectionPathResult[]; /** The connection currently being worked on */ currentConnection: ConnectionPathResult | null; /** Total number of connections (for progress calculation) */ totalConnectionCount: number; currentPathIterations: number; candidates?: PortPointCandidate[] | null; /** Tracks visited port point IDs to avoid revisiting */ visitedPortPoints?: Set | null; connectionNameToGoalNodeIds: Map; capacityMeshNodeMap: Map; /** Heuristic scaling: an estimate of "node pitch" used to estimate remaining hops */ avgNodePitch: number; /** Whether the current connection should be forced to route off-board */ currentConnectionShouldRouteOffBoard: boolean; activeCandidateStraightLineDistance?: number; /** Cached list of off-board nodes for computing distance to nearest off-board node */ offBoardNodes: InputNodeWithPortPoints[]; /** Cache of base node cost (cost of node in current committed state) */ private baseNodeCostCache; constructor(input: { simpleRouteJson: SimpleRouteJson; capacityMeshNodes: CapacityMeshNode[]; inputNodes: InputNodeWithPortPoints[]; colorMap?: Record; nodeMemoryPfMap?: Map; hyperParameters?: Partial; precomputedInitialParams?: PrecomputedInitialParams; /** Pre-routed connections that should not be re-routed but should appear in results */ fixedRoutes?: ConnectionPathResult[]; }); getConstructorParams(): { simpleRouteJson: SimpleRouteJson; capacityMeshNodes: CapacityMeshNode[]; inputNodes: InputNodeWithPortPoints[]; colorMap?: Record; nodeMemoryPfMap?: Map; hyperParameters?: Partial; precomputedInitialParams?: PrecomputedInitialParams; /** Pre-routed connections that should not be re-routed but should appear in results */ fixedRoutes?: ConnectionPathResult[]; }; private clearCostCaches; private clampPf; /** Convert Pf into an additive "failure cost" */ private pfToFailureCost; /** Base node cost with the currently-committed port points (no candidate additions) */ private getBaseNodeFailureCost; computeBoardScore(): number; getMaxIterationsForCurrentPath(): number; /** * Exact delta cost of routing this connection through `nodeId` * for the segment defined by entry->exit. * * This is computed as: * delta = (-log(1-pfAfter)) - (-log(1-pfBefore)) * and then scaled by NODE_PF_FACTOR. */ private getNodeDeltaFailureCostForSegment; getConnectionsWithNodes(): { connectionsWithResults: ConnectionPathResult[]; connectionNameToGoalNodeIds: Map; }; /** * Build a NodeWithPortPoints structure for crossing calculation. */ buildNodeWithPortPointsForCrossing(node: InputNodeWithPortPoints, additionalPortPoints?: PortPoint[]): NodeWithPortPoints; /** * Compute probability of failure for a node using getIntraNodeCrossings. */ computeNodePf(node: InputNodeWithPortPoints, additionalPortPoints?: PortPoint[]): number; /** * Get penalty for reusing a port point that's already assigned. * No penalty if the port point is assigned to a connection with the same rootConnectionName. */ getPortPointReusePenalty(portPointId: string, rootConnectionName?: string): number; /** * Get the node on the "other side" of a port point from the given node */ getOtherNodeId(portPoint: InputPortPoint, currentNodeId: CapacityMeshNodeId): CapacityMeshNodeId | null; /** * Exact step cost from prevCandidate to exiting current node via `exitPortPoint`. * * IMPORTANT: This charges Pf delta for the node we are *leaving* (prevCandidate.currentNodeId), * because only then we know both entry and exit points inside that node. */ computeG(prevCandidate: PortPointCandidate, exitPortPoint: InputPortPoint, _targetNodeId: CapacityMeshNodeId, connectionName: string, rootConnectionName?: string): number; /** * Final "close" cost when you're already in the end node and you connect to the end target point. * This ensures the last node's segment is accounted for in g. */ private computeGToEndTarget; /** * Compute distance to the nearest off-board node from a point. */ computeDistanceToNearestOffBoardNode(point: { x: number; y: number; }): number; /** * Heuristic: approximate remaining cost. * * Uses: * - distance to goal * - estimated remaining hops (distance / avgNodePitch) * - memoryPfMap to bias away from historically high Pf regions */ computeH(point: InputPortPoint, currentNodeId: CapacityMeshNodeId, endGoalNodeId: CapacityMeshNodeId, currentZ: number, distanceTraveled: number, hasTouchedOffBoardNode?: boolean): number; getVisitedPortPointKey(portPointId: string, hasTouchedOffBoardNode?: boolean): string; getAvailableExitPortPoints(nodeId: CapacityMeshNodeId, hasTouchedOffBoardNode?: boolean): InputPortPoint[]; /** * Get available port points to exit from a node, but *do not* return all. * * Rule: * - For each (neighborNodeId, z) group, return the centermost (smallest dist). * - If that centermost port point is already assigned, also return some next-closest * unassigned offsets as backups. */ getAvailableExitPortPointsWithOmissions(nodeId: CapacityMeshNodeId, _endGoalNodeId: CapacityMeshNodeId, hasTouchedOffBoardNode?: boolean): InputPortPoint[]; getAvailableExitPortPointsForOffboardConnection(nodeId: CapacityMeshNodeId, hasTouchedOffBoardNode?: boolean): (InputPortPoint & { throughNodeId: CapacityMeshNodeId; })[]; canTravelThroughObstacle(node: InputNodeWithPortPoints, connectionName: string, rootConnectionName: string): boolean; /** * Check if we've reached the end goal node */ isAtEndGoal(currentNodeId: CapacityMeshNodeId, endGoalNodeId: CapacityMeshNodeId): boolean; getBacktrackedPath(candidate: PortPointCandidate): PortPointCandidate[]; /** * Assign port points along a path and record which connections use them. */ assignPortPointsForPath(path: PortPointCandidate[], connectionName: string, rootConnectionName?: string): PortPoint[]; /** * Add start/end target points to nodes for crossing calculations. */ addTargetPointsToNodes(path: PortPointCandidate[], connection: SimpleRouteConnection): void; /** * Check if a port point is already in the candidate's path chain. */ isPortPointInPathChain(candidate: PortPointCandidate | null, portPointId: string): boolean; /** * Prevent node cycles in a single candidate chain. * This is important for correctness because we charge node cost as "one segment per node". */ isNodeInPathChain(candidate: PortPointCandidate | null, nodeId: CapacityMeshNodeId): boolean; _step(): void; /** * Get the nodes with port points for the HighDensitySolver */ getNodesWithPortPoints(): NodeWithPortPoints[]; /** * Get all connections that pass through a given node (excluding a specific connection). */ getConnectionsInNode(nodeId: CapacityMeshNodeId, excludeConnectionName?: string): ConnectionPathResult[]; /** * Compute the pf and crossing count of a node with a specific connection removed (for test-ripping). */ computeNodePfWithoutConnection(node: InputNodeWithPortPoints, connectionNameToRemove: string): { pf: number; totalCrossings: number; }; /** * Compute the current crossing count for a node. */ computeNodeCrossings(node: InputNodeWithPortPoints): number; /** * Rip a connection: unassign all its port points and clear its path. * The connection will be re-routed later. */ ripConnection(connectionResult: ConnectionPathResult): void; /** * Requeue a connection by moving it to the unprocessed queue for re-routing. * If already processed, moves it from processed to unprocessed. * If still unprocessed, moves it to the front for priority re-routing. * Returns false if MAX_RIPS exceeded (solver should fail). */ requeueConnection(connectionResult: ConnectionPathResult): boolean; /** * Process ripping for high-pf nodes after a path is solved. * For each node with pf > RIPPING_PF_THRESHOLD that the path goes through, * test-rip connections until pf is below threshold. */ processRippingForPath(path: PortPointCandidate[], justRoutedConnectionName: string): void; /** * Randomly rip a fraction of already-routed connections to help escape local minima. * Rips (RANDOM_RIP_FRACTION * 100)% of processed connections, with a minimum of 1. */ private processRandomRipping; visualize(): GraphicsObject; } type Side = "left" | "right" | "top" | "bottom"; type OwnerPair = [string, string]; type OwnerPairKey = string; type EdgeOrientation = "vertical" | "horizontal"; type Bounds = { minX: number; maxX: number; minY: number; maxY: number; }; type PortPointWithOwnerPair = PortPoint & { ownerNodeIds: OwnerPair; ownerPairKey: OwnerPairKey; }; type SharedEdge = { ownerNodeIds: OwnerPair; ownerPairKey: OwnerPairKey; orientation: EdgeOrientation; x1: number; y1: number; x2: number; y2: number; center: { x: number; y: number; }; length: number; nodeSideByOwnerId: Record; }; interface UniformPortDistributionSolverInput { nodeWithPortPoints: NodeWithPortPoints[]; inputNodesWithPortPoints: InputNodeWithPortPoints[]; obstacles: Obstacle[]; } /** * Redistributes port points uniformly along the sides of nodes to optimize * routing density and prevent congestion. * * This solver: * 1. Determines an owner pair of capacity nodes for each port point. * 2. Precomputes the shared edge for each owner pair. * 3. Evenly spaces "family" port points along their shared edge. */ declare class UniformPortDistributionSolver extends BaseSolver$1 { private input; getSolverName(): string; mapOfNodeIdToBounds: Map; mapOfOwnerPairToPortPoints: Map; mapOfOwnerPairToSharedEdge: Map; ownerPairsToProcess: OwnerPairKey[]; currentOwnerPairBeingProcessed: OwnerPairKey | null; redistributedNodes: NodeWithPortPoints[]; constructor(input: UniformPortDistributionSolverInput); step(): void; rebuildNodes(): void; getOutput: () => NodeWithPortPoints[]; visualize(): GraphicsObject; } interface SegmentPortPoint { segmentPortPointId: string; x: number; y: number; availableZ: number[]; nodeIds: [CapacityMeshNodeId, CapacityMeshNodeId]; edgeId: string; /** The connection name currently using this port point, or null if unused */ connectionName: string | null; rootConnectionName?: string; /** XY distance to the centermost port on this Z level (centermost port has distance 0) */ distToCentermostPortOnZ: number; /** * This is special port point that is created in narrow gaps, and only kept when otherwise reaching the obstacle is impossible * ideally this port points should be discarded but we need them in some cases */ cramped: boolean; /** Extra tiny-hypergraph traversal cost for fallback ports. */ tinyHypergraphPortPenalty?: number; } interface SharedEdgeSegment { edgeId: string; nodeIds: [CapacityMeshNodeId, CapacityMeshNodeId]; start: { x: number; y: number; }; end: { x: number; y: number; }; availableZ: number[]; portPoints: SegmentPortPoint[]; } /** * AvailableSegmentPointSolver computes port points on shared edges between * capacity mesh nodes. These points can be used for routing traces through * the capacity mesh. * * For each edge shared between two nodes: * 1. Computes the shared edge segment * 2. Determines how many port points can fit based on traceWidth * 3. Creates port points evenly spaced along the segment * * Port points start as unused (connectionName = null) and are assigned * as paths are routed through them. */ declare class AvailableSegmentPointSolver extends BaseSolver { getSolverName(): string; nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; traceWidth: number; obstacleMargin: number; minPortSpacing: number; nodeMap: Map; nodeEdgeMap: Map; /** All shared edge segments with their port points */ sharedEdgeSegments: SharedEdgeSegment[]; /** Map from edgeId to SharedEdgeSegment for quick lookup */ edgeSegmentMap: Map; /** Map from segmentPortPointId to SegmentPortPoint */ portPointMap: Map; colorMap: Record; shouldReturnCrampedPortPoints: boolean; constructor({ nodes, edges, traceWidth, obstacleMargin, colorMap, shouldReturnCrampedPortPoints, }: { nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; traceWidth: number; obstacleMargin?: number; colorMap?: Record; shouldReturnCrampedPortPoints: boolean; }); _step(): void; private computeAllSharedEdgeSegments; private computeSharedEdgeSegment; /** * Check if we should skip creating port points between an off-board node and a middle node. * Returns true if the middle node is connected to another node with the same offBoardConnectionId, * exactly 2 nodes have that ID, and their midpoint is inside the middle node. */ private shouldSkipOffBoardPortPoint; private findOverlappingSegment; /** * Find available port points for traveling between two nodes */ getAvailablePortPointsBetweenNodes(nodeId1: CapacityMeshNodeId, nodeId2: CapacityMeshNodeId): SegmentPortPoint[]; /** * Get all port points (both assigned and unassigned) for an edge between nodes */ getPortPointsForEdge(nodeId1: CapacityMeshNodeId, nodeId2: CapacityMeshNodeId): SegmentPortPoint[]; /** * Assign a port point to a connection */ assignPortPoint(segmentPortPointId: string, connectionName: string, rootConnectionName?: string): boolean; /** * Release a port point (make it available again) */ releasePortPoint(segmentPortPointId: string): boolean; /** * Get the count of available port points on an edge */ getAvailablePortCountForEdge(nodeId1: CapacityMeshNodeId, nodeId2: CapacityMeshNodeId): number; getOutput(): SharedEdgeSegment[]; visualize(): GraphicsObject; } declare class CapacityMeshEdgeSolver extends BaseSolver { nodes: CapacityMeshNode[]; getSolverName(): string; edges: Array; /** Only used for visualization, dynamically instantiated if necessary */ nodeMap?: Map; constructor(nodes: CapacityMeshNode[]); getNextCapacityMeshEdgeId(): string; _step(): void; handleTargetNodes(): void; doNodesHaveSharedLayer(node1: CapacityMeshNode, node2: CapacityMeshNode): boolean; hasEdgeBetween(node1: CapacityMeshNode, node2: CapacityMeshNode): boolean; doNodesTouchOrOverlap(node1: CapacityMeshNode, node2: CapacityMeshNode): boolean; visualize(): GraphicsObject; } declare class CapacityMeshEdgeSolver2_NodeTreeOptimization extends CapacityMeshEdgeSolver { nodes: CapacityMeshNode[]; getSolverName(): string; private nodeTree; private currentNodeIndex; private edgeSet; constructor(nodes: CapacityMeshNode[]); _step(): void; } /** * Merge targets that are close to each other into a single target */ declare class CapacityNodeTargetMerger extends BaseSolver { nodes: CapacityMeshNode[]; connMap: ConnectivityMap; getSolverName(): string; unprocessedObstacles: Obstacle[]; newNodes: CapacityMeshNode[]; removedNodeIds: Set; constructor(nodes: CapacityMeshNode[], obstacles: Obstacle[], connMap: ConnectivityMap); _step(): void; visualize(): GraphicsObject; } declare class DeadEndSolver extends BaseSolver { getSolverName(): string; removedNodeIds: Set; private targetNodeIds; private leaves; private leavesIndex; private adjacencyList; /** Only used for visualization, dynamically instantiated if necessary */ nodeMap?: Map; private nodes; private edges; constructor({ nodes, edges, }: { nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; }); _step(): void; visualize(): GraphicsObject; } interface HighDensityHyperParameters { FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: number; FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: number; FUTURE_CONNECTION_PROXIMITY_VD: number; /** * Alternative to FUTURE_CONNECTION_PROXIMITY_VD that accepts mm * Used by high density w/ jumpers solver * */ FUTURE_CONNECTION_TRACE_PROXIMITY: number; MISALIGNED_DIST_PENALTY_FACTOR: number; VIA_PENALTY_FACTOR_2: number; SHUFFLE_SEED: number; CELL_SIZE_FACTOR: number; FLIP_TRACE_ALIGNMENT_DIRECTION: boolean; MULTI_HEAD_POLYLINE_SOLVER: boolean; SEGMENTS_PER_POLYLINE: number; BOUNDARY_PADDING: number; ITERATION_PENALTY: number; MINIMUM_FINAL_ACCEPTANCE_GAP?: number; OBSTACLE_PROX_PENALTY_FACTOR?: number; OBSTACLE_PROX_SIGMA?: number; EDGE_PROX_PENALTY_FACTOR?: number; EDGE_PROX_SIGMA?: number; ALLOW_DIAGONAL?: boolean; FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY?: number; FUTURE_CONNECTION_JUMPER_PAD_PENALTY?: number; JUMPER_JUMPER_PAD_PROXIMITY?: number; JUMPER_JUMPER_PAD_PENALTY?: number; FUTURE_CONNECTION_LINE_PROXIMITY?: number; FUTURE_CONNECTION_LINE_PENALTY?: number; MIN_TRAVEL_BEFORE_JUMPER?: number; } type Node = { x: number; y: number; z: number; g: number; h: number; f: number; parent: Node | null; }; declare class SingleRouteCandidatePriorityQueue { private heap; constructor(nodes: T[]); private getLeftChildIndex; private getRightChildIndex; private getParentIndex; private hasLeftChild; private hasRightChild; private hasParent; private leftChild; private rightChild; private parent; private swap; dequeue(): T | null; peek(): T | null; enqueue(item: T): void; heapifyUp(): void; heapifyDown(): void; /** * Returns the top N candidates sorted by f value (lowest first) */ getTopN(n: number): T[]; } type FutureConnection$1 = { connectionName: string; rootConnectionName?: string; regionId?: string; points: { x: number; y: number; z: number; }[]; }; declare class SingleHighDensityRouteSolver extends BaseSolver { getSolverName(): string; obstacleRoutes: HighDensityIntraNodeRoute$1[]; bounds: { minX: number; maxX: number; minY: number; maxY: number; }; boundsSize: { width: number; height: number; }; boundsCenter: { x: number; y: number; }; A: { x: number; y: number; z: number; }; B: { x: number; y: number; z: number; }; straightLineDistance: number; viaDiameter: number; traceThickness: number; obstacleMargin: number; layerCount: number; availableZ: number[]; minCellSize: number; cellStep: number; GREEDY_MULTIPLER: number; numRoutes: number; VIA_PENALTY_FACTOR: number; CELL_SIZE_FACTOR: number; NEARBY_SEGMENT_CLEARANCE: number; exploredNodes: Set; candidates: SingleRouteCandidatePriorityQueue; connectionName: string; rootConnectionName?: string; regionId?: string; solvedPath: HighDensityIntraNodeRoute$1 | null; futureConnections: FutureConnection$1[]; hyperParameters: Partial; connMap?: ConnectivityMap; obstacleSegments: IndexedObstacleSegment[]; obstacleSegmentIndex: Flatbush | null; obstacleVias: IndexedObstacleVia[]; obstacleViaIndex: Flatbush | null; /** For debugging/animating the exploration */ debug_exploredNodesOrdered: string[]; debug_nodesTooCloseToObstacle: Set; debug_nodePathToParentIntersectsObstacle: Set; debugEnabled: boolean; initialNodeGridOffset: { x: number; y: number; }; constructor(opts: { connectionName: string; rootConnectionName?: string; regionId?: string; obstacleRoutes: HighDensityIntraNodeRoute$1[]; minDistBetweenEnteringPoints: number; bounds: { minX: number; maxX: number; minY: number; maxY: number; }; A: { x: number; y: number; z: number; }; B: { x: number; y: number; z: number; }; viaDiameter?: number; traceThickness?: number; obstacleMargin?: number; layerCount?: number; availableZ?: number[]; futureConnections?: FutureConnection$1[]; hyperParameters?: Partial; connMap?: ConnectivityMap; nearbySegmentClearance?: number; }); handleSimpleCases(): void; get viaPenaltyDistance(): number; isNodeTooCloseToObstacle(node: Node, margin?: number, isVia?: boolean): boolean; isNodeTooCloseToEdge(node: Node, isVia?: boolean): boolean; doesPathToParentIntersectObstacle(node: Node): boolean; buildObstacleIndexes(): void; computeH(node: Node): number; computeG(node: Node): number; computeF(g: number, h: number): number; getNodeKey(node: Node): string; getNeighbors(node: Node): Node[]; getNodePath(node: Node): Node[]; getViasInNodePath(node: Node): { x: number; y: number; }[]; setSolvedPath(node: Node): void; computeProgress(currentNode: Node, goalDist: number, isOnLayer: boolean): number; _step(): void; visualize(): GraphicsObject; } type IndexedObstacleSegment = { z: number; A: { x: number; y: number; z: number; }; B: { x: number; y: number; z: number; }; connectedToCurrentConnection: boolean; }; type IndexedObstacleVia = { x: number; y: number; }; type ConnectionPoint = { x: number; y: number; z: number; }; declare class IntraNodeRouteSolver extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; colorMap: Record; unsolvedConnections: { connectionName: string; rootConnectionName?: string; points: { x: number; y: number; z: number; }[]; }[]; originalConnectionPointsByName: Map; rootConnectionNameByConnectionName: Map; totalConnections: number; solvedRoutes: HighDensityIntraNodeRoute$1[]; failedSubSolvers: SingleHighDensityRouteSolver[]; hyperParameters: Partial; minDistBetweenEnteringPoints: number; viaDiameter: number; traceWidth: number; obstacleMargin: number; rerouteAttemptsByConnection: Map; POSTROUTE_VIA_TRACE_CLEARANCE: number; MAX_POSTROUTE_REPAIR_ATTEMPTS: number; activeSubSolver: SingleHighDensityRouteSolver | null; connMap?: ConnectivityMap; get failedSolvers(): SingleHighDensityRouteSolver[]; get activeSolver(): SingleHighDensityRouteSolver | null; constructor(params: { nodeWithPortPoints: NodeWithPortPoints; colorMap?: Record; hyperParameters?: Partial; connMap?: ConnectivityMap; viaDiameter?: number; traceWidth?: number; obstacleMargin?: number; obstacles?: Obstacle[]; layerCount?: number; }); computeProgress(): number; private getSingleRouteSolverOpts; private trySolveSamePointLayerChange; private queueExtraBranchesForMultiPointConnection; private getAvailableZLayers; private getFirstSolvedViaTraceConflict; private queueConnectionForPostrouteRepair; _step(): void; visualize(): GraphicsObject; } type CachedSolvedIntraNodeRouteSolver = { success: true; solvedRoutes: HighDensityIntraNodeRoute$1[]; } | { success: false; error?: string; }; type CacheToIntraNodeSolverTransform = Record; declare class CachedIntraNodeRouteSolver extends IntraNodeRouteSolver implements CachableSolver { getSolverName(): string; cacheProvider: CacheProvider | null; cacheHit: boolean; hasAttemptedToUseCache: boolean; cacheKey?: string | undefined; cacheToSolveSpaceTransform?: CacheToIntraNodeSolverTransform | undefined; initialUnsolvedConnections: { connectionName: string; points: { x: number; y: number; z: number; }[]; }[]; constructor(params: ConstructorParameters[0] & { cacheProvider?: CacheProvider | null; }); _step(): void; computeCacheKeyAndTransform(): { cacheKey: string; cacheToSolveSpaceTransform: CacheToIntraNodeSolverTransform; }; applyCachedSolution(cachedSolution: CachedSolvedIntraNodeRouteSolver): void; attemptToUseCacheSync(): boolean; saveToCacheSync(): void; } declare class SingleLayerNoDifferentRootIntersectionsIntraNodeSolver extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; traceWidth: number; viaDiameter: number; solvedRoutes: HighDensityIntraNodeRoute$1[]; constructor(params: { nodeWithPortPoints: NodeWithPortPoints; traceWidth?: number; viaDiameter?: number; }); static isApplicable(node: NodeWithPortPoints): boolean; private buildTaskGroups; private trySolveNode; _step(): void; visualize(): GraphicsObject; } type Route$3 = { A: PortPoint; B: PortPoint; connectionName: string; }; type NodeBounds = { minX: number; maxX: number; minY: number; maxY: number; }; declare class SingleTransitionIntraNodeSolver extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; routes: Route$3[]; viaDiameter: number; traceThickness: number; obstacleMargin: number; solvedRoutes: HighDensityIntraNodeRoute$1[]; bounds: NodeBounds; constructor(params: { nodeWithPortPoints: NodeWithPortPoints; viaDiameter?: number; traceThickness?: number; obstacleMargin?: number; }); /** * Groups node port points into explicit route tasks. * * @returns One route record per discovered port-point pair. */ private extractRoutesFromNode; /** * Computes the rectangular routing bounds of the current node. * * @returns Axis-aligned node bounds in board coordinates. */ private calculateBounds; /** * Builds the solved route for a single via transition. * * @param params - Route endpoints, via location, and connection metadata. * @returns A solved high-density route containing a single via. */ private createTransitionRoute; _step(): void; visualize(): GraphicsObject; } type Route$2 = { A: PortPoint; B: PortPoint; connectionName: string; rootConnectionName?: string; }; type LayeredObstacle = Obstacle & { zLayers: number[]; }; declare class SingleTransitionThroughObstacleIntraNodeSolver extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; routes: Route$2[]; obstacles: LayeredObstacle[]; viaDiameter: number; traceThickness: number; connMap?: ConnectivityMap; solvedRoutes: HighDensityIntraNodeRoute$1[]; constructor(params: { nodeWithPortPoints: NodeWithPortPoints; obstacles?: Obstacle[]; connMap?: ConnectivityMap; layerCount?: number; viaDiameter?: number; traceThickness?: number; }); static isApplicable(params: { nodeWithPortPoints: NodeWithPortPoints; obstacles?: Obstacle[]; connMap?: ConnectivityMap; layerCount?: number; }): boolean; /** * Builds explicit route tasks from linked port-point pairs in the node. * * @returns Route tasks ready for obstacle validation. */ private extractRoutesFromNode; /** * Finds a same-net multilayer obstacle that contains both route endpoints. * * @param route - Route to validate. * @returns Matching obstacle, or `null` when none exists. */ private getContainingThroughObstacle; _step(): void; visualize(): GraphicsObject; } type Point$4 = { x: number; y: number; z?: number; }; type Route$1 = { A: Point$4; B: Point$4; connectionName: string; }; /** * Solver for exactly two crossing routes where exactly one route transitions * between layers. * * This solver only handles port points that lie on node bounds. * - Outside node bounds: treated as invalid input and reported as an error. * - Strictly inside node bounds: solver marks itself as failed (out of scope). */ declare class SingleTransitionCrossingRouteSolver extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; routes: Route$1[]; viaDiameter: number; traceThickness: number; obstacleMargin: number; layerCount: number; debugViaPositions: { via: Point$4; }[]; solvedRoutes: HighDensityIntraNodeRoute$1[]; bounds: { minX: number; maxX: number; minY: number; maxY: number; }; constructor(params: { nodeWithPortPoints: NodeWithPortPoints; viaDiameter?: number; traceThickness?: number; obstacleMargin?: number; layerCount?: number; }); /** * Extract routes that need to be connected from the node data */ private extractRoutesFromNode; /** * Calculate the bounding box of the node */ private calculateBounds; /** * Classifies a point relative to this node's bounds. * Uses epsilon to tolerate floating-point noise on boundary coordinates. */ private getPortPointBoundsPosition; /** * Check if two routes are crossing */ private doRoutesCross; private calculateViaPosition; /** * Create a single transition route with properly placed via */ private createTransitionRoute; /** * Create the non-transition route */ private createFlatRoute; /** * Try to solve with one route having a transition and the other staying flat */ private trySolve; /** * Main step method that attempts to solve the routes */ _step(): void; /** * Visualization for debugging */ visualize(): GraphicsObject; /** * Get the solved routes */ getSolvedRoutes(): HighDensityIntraNodeRoute$1[]; } type Point$3 = { x: number; y: number; z?: number; }; type Route = { startPort: Point$3; endPort: Point$3; connectionName: string; }; declare class TwoCrossingRoutesHighDensitySolver extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; routes: Route[]; viaDiameter: number; traceThickness: number; obstacleMargin: number; layerCount: number; debugViaPositions: { via1: Point$3; via2: Point$3; }[]; escapeLayer: number; solvedRoutes: HighDensityIntraNodeRoute$1[]; bounds: { minX: number; maxX: number; minY: number; maxY: number; }; constructor(params: { nodeWithPortPoints: NodeWithPortPoints; viaDiameter?: number; traceThickness?: number; obstacleMargin?: number; layerCount?: number; }); /** * Extract routes that need to be connected from the node data */ private extractRoutesFromNode; /** * Calculate the bounding box of the node */ private calculateBounds; /** * Check if two routes are crossing */ private doRoutesCross; private calculateViaPositions; /** * Try to solve with routeA going over and routeB staying on layer 0 */ private trySolveAOverB; private pushViasFromEndpoints; private getMinDistanceBetweenViaCenters; private moveViasAsCloseAsPossible; handleRoutesDontCross(): void; /** * Main step method that attempts to solve the two crossing routes */ _step(): void; /** * Visualization for debugging */ visualize(): GraphicsObject; /** * Get the solved routes */ getSolvedRoutes(): HighDensityIntraNodeRoute$1[]; } type SupervisedSolver = { hyperParameters: any; solver: T; h: number; g: number; f: number; }; type HyperParameterDef = { name: string; possibleValues: Array; }; /** * The HyperParameterSupervisorSolver is a solver that solves a problem by * running competing solvers with different hyperparameters. * * As solvers make progress, the supervisor will allow the best solvers to run * for more iterations, prioritizing the solvers that are working the best. */ declare class HyperParameterSupervisorSolver extends BaseSolver { getSolverName(): string; GREEDY_MULTIPLIER: number; MIN_SUBSTEPS: number; supervisedSolvers?: Array>; winningSolver?: T; getHyperParameterDefs(): Array; getCombinationDefs(): Array> | null; getHyperParameterCombinations(hyperParameterDefs?: Array): Array>; initializeSolvers(): void; generateSolver(hyperParameters: any): T; computeG(solver: T): number; computeH(solver: T): number; computeF(g: number, h: number): number; getSupervisedSolverWithBestFitness(): SupervisedSolver | null; getFailureMessage(): string; _step(): void; onSolve(solver: SupervisedSolver): void; visualize(): GraphicsObject; } declare class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver { getSolverName(): string; constructorParams: ConstructorParameters[0]; solvedRoutes: HighDensityIntraNodeRoute$1[]; nodeWithPortPoints: NodeWithPortPoints; connMap?: ConnectivityMap; effort: number; constructor(opts: ConstructorParameters[0] & { effort?: number; }); getCombinationDefs(): string[][]; getHyperParameterDefs(): ({ name: string; possibleValues: { SINGLE_LAYER_NO_DIFFERENT_ROOT_INTERSECTIONS: boolean; }[]; } | { name: string; possibleValues: ({ FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: number; FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: number; FUTURE_CONNECTION_PROXIMITY_VD: number; MISALIGNED_DIST_PENALTY_FACTOR: number; VIA_PENALTY_FACTOR_2?: undefined; } | { FUTURE_CONNECTION_PROX_TRACE_PENALTY_FACTOR: number; FUTURE_CONNECTION_PROX_VIA_PENALTY_FACTOR: number; FUTURE_CONNECTION_PROXIMITY_VD: number; MISALIGNED_DIST_PENALTY_FACTOR: number; VIA_PENALTY_FACTOR_2: number; })[]; } | { name: string; possibleValues: { SHUFFLE_SEED: number; }[]; } | { name: string; possibleValues: { CELL_SIZE_FACTOR: number; }[]; } | { name: string; possibleValues: { FLIP_TRACE_ALIGNMENT_DIRECTION: boolean; }[]; } | { name: string; possibleValues: { CELL_SIZE_FACTOR: number; VIA_PENALTY_FACTOR_2: number; }[]; } | { name: string; possibleValues: { THROUGH_OBSTACLE: boolean; }[]; } | { name: string; possibleValues: { CLOSED_FORM_SINGLE_TRANSITION: boolean; }[]; } | { name: string; possibleValues: ({ MULTI_HEAD_POLYLINE_SOLVER: boolean; SEGMENTS_PER_POLYLINE: number; BOUNDARY_PADDING: number; ITERATION_PENALTY?: undefined; MINIMUM_FINAL_ACCEPTANCE_GAP?: undefined; } | { MULTI_HEAD_POLYLINE_SOLVER: boolean; SEGMENTS_PER_POLYLINE: number; BOUNDARY_PADDING: number; ITERATION_PENALTY: number; MINIMUM_FINAL_ACCEPTANCE_GAP: number; })[]; } | { name: string; possibleValues: { HIGH_DENSITY_A01: boolean; }[]; } | { name: string; possibleValues: { HIGH_DENSITY_A03: boolean; }[]; })[]; computeG(solver: IntraNodeRouteSolver): number; computeH(solver: IntraNodeRouteSolver): number; generateSolver(hyperParameters: any): IntraNodeRouteSolver; onSolve(solver: SupervisedSolver): void; } type HyperSingleIntraNodeSolverParams = ConstructorParameters[0]; type GrowShrinkHighDensityIntraNodeSolverParams = HyperSingleIntraNodeSolverParams & { maxGrowthAttempts?: number; maxInnerIterationsPerGrowthAttempt?: number; fallbackToInvalidGeometryOnFailure?: boolean; }; declare class GrowShrinkHighDensityIntraNodeSolver extends BaseSolver { getSolverName(): string; constructorParams: GrowShrinkHighDensityIntraNodeSolverParams; nodeWithPortPoints: NodeWithPortPoints; solvedRoutes: HighDensityIntraNodeRoute$1[]; failedSolvers: HyperSingleIntraNodeSolver[]; activeSubSolver: HyperSingleIntraNodeSolver | null; winningSolver?: HyperSingleIntraNodeSolver; scaleFactor: number; growthAttempts: number; maxGrowthAttempts: number; constructor(params: GrowShrinkHighDensityIntraNodeSolverParams); getConstructorParams(): GrowShrinkHighDensityIntraNodeSolverParams; private createActiveSubSolver; private acceptSolution; computeProgress(): number; _step(): void; visualize(): GraphicsObject; } type HighDensityIntraNodeSolver = IntraNodeRouteSolver | HyperSingleIntraNodeSolver | GrowShrinkHighDensityIntraNodeSolver; declare class HighDensitySolver extends BaseSolver { getSolverName(): string; unsolvedNodePortPoints: NodeWithPortPoints[]; routes: HighDensityIntraNodeRoute$1[]; colorMap: Record; readonly defaultViaDiameter = 0.3; readonly defaultTraceThickness = 0.15; viaDiameter: number; traceWidth: number; obstacleMargin: number; effort: number; obstacles: Obstacle[]; layerCount: number; useGrowShrinkHighDensityIntraNodeSolver: boolean; growShrinkMaxInnerIterationsPerGrowthAttempt?: number; growShrinkFallbackToInvalidGeometryOnFailure: boolean; failedSolvers: HighDensityIntraNodeSolver[]; activeSubSolver: HighDensityIntraNodeSolver | null; connMap?: ConnectivityMap; nodePfById: Map; nodeSolveMetadataById: Map; constructor({ nodePortPoints, colorMap, connMap, viaDiameter, traceWidth, obstacleMargin, effort, nodePfById, obstacles, layerCount, useGrowShrinkHighDensityIntraNodeSolver, growShrinkMaxInnerIterationsPerGrowthAttempt, growShrinkFallbackToInvalidGeometryOnFailure, }: { nodePortPoints: NodeWithPortPoints[]; colorMap?: Record; connMap?: ConnectivityMap; viaDiameter?: number; traceWidth?: number; obstacleMargin?: number; effort?: number; obstacles?: Obstacle[]; layerCount?: number; useGrowShrinkHighDensityIntraNodeSolver?: boolean; growShrinkMaxInnerIterationsPerGrowthAttempt?: number; growShrinkFallbackToInvalidGeometryOnFailure?: boolean; nodePfById?: Map | Record; }); private getSolvedNodeSolverType; private recordNodeSolveMetadata; private createNodeMarkerLabel; private getConcreteSolverTypeName; private getIntraNodeStrategyName; private recordSolvedNodeStats; private recordResizeStats; /** * Each iteration, pop an unsolved node and attempt to find the routes inside * of it. */ _step(): void; private updateCacheStats; visualize(): GraphicsObject; } interface PortPointSectionParams { centerOfSectionCapacityNodeId: CapacityMeshNodeId; expansionDegrees: number; } /** * A path segment that has been "cut" to fit within a section. * Contains the portion of the path that passes through section nodes, * plus entry/exit information for later reattachment. */ interface SectionPath { /** The connection name this path belongs to */ connectionName: string; /** Root connection name if applicable */ rootConnectionName?: string; /** The cut path points (only the portion within the section) */ points: Array<{ x: number; y: number; z: number; nodeId: CapacityMeshNodeId; portPointId?: string; }>; /** Index in original path where this segment starts */ originalStartIndex: number; /** Index in original path where this segment ends */ originalEndIndex: number; /** True if path enters from outside the section */ hasEntryFromOutside: boolean; /** True if path exits to outside the section */ hasExitToOutside: boolean; } interface PortPointSection { /** The center node ID for this section */ centerNodeId: CapacityMeshNodeId; /** How many hops from center this section covers */ expansionDegrees: number; /** All node IDs included in this section */ nodeIds: Set; /** Input nodes filtered to just those in this section */ inputNodes: InputNodeWithPortPoints[]; /** Capacity mesh nodes filtered to just those in this section */ capacityMeshNodes: CapacityMeshNode[]; /** Edges that connect nodes within this section */ internalEdges: CapacityMeshEdge[]; /** Edges that connect section nodes to external nodes (boundary edges) */ boundaryEdges: CapacityMeshEdge[]; /** Paths that pass through this section, cut to fit within section bounds */ sectionPaths: SectionPath[]; } interface CreatePortPointSectionInput { /** All input nodes with port points from PortPointPathingSolver */ inputNodes: InputNodeWithPortPoints[]; /** All capacity mesh nodes */ capacityMeshNodes: CapacityMeshNode[]; /** All capacity mesh edges */ capacityMeshEdges: CapacityMeshEdge[]; /** Map from node ID to input node for quick lookup */ nodeMap: Map; /** Connection path results from PortPointPathingSolver */ connectionResults?: ConnectionPathResult[]; } type HyperParameterScheduleEntry = PortPointPathingHyperParameters & { EXPANSION_DEGREES: number; }; interface MultiSectionPortPointOptimizerParams { JUMPER_PF_FN_ENABLED?: boolean; simpleRouteJson: SimpleRouteJson; inputNodes: InputNodeWithPortPoints[]; capacityMeshNodes: CapacityMeshNode[]; capacityMeshEdges: CapacityMeshEdge[]; colorMap?: Record; SHUFFLE_SEEDS_PER_SECTION?: number | null; /** Results from the initial PortPointPathingSolver run */ initialConnectionResults: ConnectionPathResult[]; /** Assigned port points from initial run */ initialAssignedPortPoints: Map; /** Node assigned port points from initial run */ initialNodeAssignedPortPoints: Map; effort?: number; /** * Fraction of connections in a section to rip/replace (0-1). * Default 1 means rip all connections. Values less than 1 keep some traces. */ FRACTION_TO_REPLACE?: number; /** * If true, always rip connections that have same-layer intersections, * even if they would otherwise be kept due to FRACTION_TO_REPLACE. */ ALWAYS_RIP_INTERSECTIONS?: boolean; /** * Maximum number of attempts to fix a single node before moving on. * Default is 100. */ MAX_ATTEMPTS_PER_NODE?: number; /** * Maximum total number of section optimization attempts. * Default is 500. */ MAX_SECTION_ATTEMPTS?: number; /** * Custom hyperparameter schedule for optimization. * Each entry defines parameters for one optimization attempt. */ HYPERPARAMETER_SCHEDULE?: HyperParameterScheduleEntry[]; } /** * MultiSectionPortPointOptimizer runs local optimization on sections of the * port point graph. It takes the output of PortPointPathingSolver and attempts * to improve routing by re-running the solver on localized sections. * * This phase runs after portPointPathingSolver to refine routes in problematic areas. */ declare class MultiSectionPortPointOptimizer extends BaseSolver { getSolverName(): string; simpleRouteJson: SimpleRouteJson; inputNodes: InputNodeWithPortPoints[]; capacityMeshNodes: CapacityMeshNode[]; capacityMeshEdges: CapacityMeshEdge[]; colorMap: Record; nodeMap: Map; capacityMeshNodeMap: Map; /** Current connection results (updated as sections are optimized) */ connectionResults: ConnectionPathResult[]; /** Current assigned port points */ assignedPortPoints: Map; /** Current node assigned port points */ nodeAssignedPortPoints: Map; /** Sections that have been created for optimization */ sections: PortPointSection[]; /** Section solver currently running */ activeSubSolver: PortPointPathingSolver | null; /** Current section being optimized */ currentSection: PortPointSection | null; /** Score before optimization (for comparison) */ sectionScoreBeforeOptimization: number; /** Node ID of the center of the current section */ currentSectionCenterNodeId: CapacityMeshNodeId | null; /** Current index in the optimization schedule */ currentScheduleIndex: number; /** Probability of failure for each node */ nodePfMap: Map; /** Number of attempts to fix each node */ attemptsToFixNode: Map; /** Total number of section optimization attempts made */ sectionAttempts: number; /** Maximum number of attempts per node */ MAX_ATTEMPTS_PER_NODE: number; /** Maximum total number of section optimization attempts */ MAX_SECTION_ATTEMPTS: number; /** Acceptable probability of failure threshold */ ACCEPTABLE_PF: number; /** * Fraction of connections in a section to rip/replace (0-1). * Default 1 means rip all connections. Values less than 1 keep some traces. */ FRACTION_TO_REPLACE: number; JUMPER_PF_FN_ENABLED: boolean; SHUFFLE_SEEDS_PER_SECTION: number | null | undefined; /** * If true, always rip connections that have same-layer intersections, * even if they would otherwise be kept due to FRACTION_TO_REPLACE. * * Uses a greedy vertex cover approach: for each intersection, only one * connection is ripped (chosen based on the shuffle seed), rather than * ripping all connections involved in intersections. */ ALWAYS_RIP_INTERSECTIONS: boolean; effort: number; /** Hyperparameter schedule for optimization attempts */ HYPERPARAMETER_SCHEDULE: HyperParameterScheduleEntry[]; constructor(params: MultiSectionPortPointOptimizerParams); /** * Compute initial Pf map for all nodes */ computeInitialPfMap(): Map; /** * Compute the score for the ENTIRE board (all nodes with port points). */ computeBoardScore(): number; /** * Compute score for a set of nodes, using the appropriate scoring function * based on JUMPER_PF_FN_ENABLED. */ computeScoreForNodes(nodesWithPortPoints: NodeWithPortPoints[]): number; /** * Recompute Pf for nodes in a section */ recomputePfForNodes(nodeIds: Set): void; /** * Create input for createPortPointSection from current state */ getCreatePortPointSectionInput(): CreatePortPointSectionInput; /** * Create a section for optimization */ createSection(params: PortPointSectionParams): PortPointSection; /** * Get nodes with port points for a section (for scoring) */ getSectionNodesWithPortPoints(section: PortPointSection): NodeWithPortPoints[]; /** * Get nodes with port points for the section (for HighDensitySolver) */ getNodesWithPortPoints(): NodeWithPortPoints[]; /** * Find the node with the highest probability of failure */ findHighestPfNode(): CapacityMeshNodeId | null; /** Cut path info for tracking during reattachment */ currentSectionCutPathInfo: Map; /** Port points from connections that are being kept (not ripped) in the current section */ currentSectionKeptPortPoints: Map; /** Connection results for connections being kept (not ripped) - used for visualization */ currentSectionFixedRoutes: ConnectionPathResult[]; /** * Determine which connections to rip based on FRACTION_TO_REPLACE and ALWAYS_RIP_INTERSECTIONS. * Returns a set of connection names that should be ripped (re-routed). */ determineConnectionsToRip(section: PortPointSection, allConnectionNames: string[]): Set; /** * Create a SimpleRouteJson for just the section's connections. * Includes both fully contained connections AND cut paths (partial connections * that pass through the section). * * Respects FRACTION_TO_REPLACE and ALWAYS_RIP_INTERSECTIONS to determine which * connections to include for re-routing. */ createSectionSimpleRouteJson(section: PortPointSection): SimpleRouteJson; /** * Prepare section input nodes for routing cut paths. * Marks nodes containing cut path endpoints as targets so the solver can route to/from them. */ prepareSectionInputNodesForCutPaths(section: PortPointSection): InputNodeWithPortPoints[]; getHyperParametersForScheduleIndex(scheduleIndex: number, sectionAttempt: number): PortPointPathingHyperParameters; /** * Create a PortPointPathingSolver for the current section. * This centralizes the solver creation logic that was previously duplicated in 3 places. */ createSectionSolver(section: PortPointSection): PortPointPathingSolver; /** * Reattach the optimized section results back to the main state. * Handles both fully contained connections AND cut paths. */ reattachSection(_section: PortPointSection, newConnectionResults: ConnectionPathResult[], newAssignedPortPoints: Map, newNodeAssignedPortPoints: Map): void; _step(): void; computeProgress(): number; visualize(): GraphicsObject; } /** * Converts a net containing many points to connect into an array of point pair * connections. * * For example, a connection with 3 pointsToConnect could be turned into 2 * connections of 2 points each. * * Where we create the minimum number of pairs, we're using a minimum spanning * tree (MST). * * Sometimes it can be used to add additional traces to help make sure we * distribute load effectively. In this version we don't do that! */ declare class NetToPointPairsSolver extends BaseSolver { ogSrj: SimpleRouteJson; colorMap: Record; getSolverName(): string; unprocessedConnections: Array; newConnections: Array; constructor(ogSrj: SimpleRouteJson, colorMap?: Record); _step(): void; getNewSimpleRouteJson(): SimpleRouteJson; visualize(): GraphicsObject; } /** * A Disjoint Set Union (DSU) or Union-Find data structure. * It tracks a collection of disjoint sets and can efficiently merge them. */ declare class DSU { private parent; /** * Creates a new DSU instance. * Each ID is initially in its own set. */ constructor(ids: string[]); /** * Finds the representative of the set containing the given ID. * Uses path compression. */ find(id: string): string; /** * Merges the sets containing the two given IDs. */ union(id1: string, id2: string): void; /** * Gets all IDs in the same set as the given ID. */ getGroup(id: string): string[]; } /** * Extends the base NetToPointPairsSolver with an optimization that utilizes * off-board connections to find shorter routing paths. * * This solver preprocesses all connections to identify points that are * electrically connected off-board (via the `isOffBoard` flag). It builds * "equivalence groups" of these points using a Disjoint Set Union (DSU) * data structure. * * When the solver processes an on-board connection or a segment from a * Minimum Spanning Tree (MST), it checks if either of the connection's * endpoints has an off-board equivalent. If so, it calculates the distance * to all possible substitutes and chooses the pair that results in the * shortest path, potentially rerouting the connection to a more optimal * equivalent point. */ declare class NetToPointPairsSolver2_OffBoardConnection extends NetToPointPairsSolver { ogSrj: SimpleRouteJson; colorMap: Record; getSolverName(): string; connectionPointDsu: DSU; connectionPointMap: Map; constructor(ogSrj: SimpleRouteJson, colorMap?: Record); _findBestConnectionPointsFromDisjointSets(sourcePoint: ConnectionPoint$1, targetPoint: ConnectionPoint$1): { pointsToConnect: [ConnectionPoint$1, ConnectionPoint$1]; }; _step(): void; } interface HyperPortPointPathingSolverParams { simpleRouteJson: SimpleRouteJson; capacityMeshNodes: CapacityMeshNode[]; inputNodes: InputNodeWithPortPoints[]; colorMap?: Record; nodeMemoryPfMap?: Map; numShuffleSeeds?: number; minAllowedBoardScore?: number; hyperParameters?: Partial; /** Pre-routed connections that should not be re-routed but should appear in results */ fixedRoutes?: ConnectionPathResult[]; /** Custom precomputed params (if provided, skips internal precomputation) */ precomputedInitialParams?: PrecomputedInitialParams; } declare class HyperPortPointPathingSolver extends HyperParameterSupervisorSolver { getSolverName(): string; private params; private precomputedInitialParams; constructor(params: HyperPortPointPathingSolverParams); getHyperParameterDefs(): Array; getCombinationDefs(): Array; generateSolver(hyperParameters: any): PortPointPathingSolver; /** * G measures the "cost" of this solver based on current score. * We use the raw board score (more negative = worse quality = higher cost). * * The key insight is that early scores (at ~25% progress) are predictive * of final quality. Solvers with better early scores tend to finish better. */ computeG(solver: PortPointPathingSolver): number; /** * H estimates remaining "cost" based on current trajectory. * * Key insight from analysis: bad solvers have similar early scores but * explode later (e.g., seed 760: -0.23 @ 25% → -15.05 final). * Good solvers maintain low scores throughout (e.g., seed 829: -0.06 @ 25% → -2.42 final). * * We estimate remaining cost by extrapolating current score/connection rate. */ computeH(solver: PortPointPathingSolver): number; /** * Get the nodes with port points from the winning solver */ getNodesWithPortPoints(): NodeWithPortPoints[]; /** * Get connection results from the winning solver */ get connectionsWithResults(): ConnectionPathResult[]; /** * Get input nodes from the winning solver */ get inputNodes(): InputNodeWithPortPoints[]; /** * Get node map from the winning solver */ get nodeMap(): Map; /** * Get assigned port points from the winning solver */ get assignedPortPoints(): Map; /** * Get node assigned port points from the winning solver */ get nodeAssignedPortPoints(): Map; computeNodePf(node: InputNodeWithPortPoints): number | null; /** * Compute board score from the winning solver */ computeBoardScore(): number; onSolve(solver: SupervisedSolver): void; visualize(): GraphicsObject; } declare class SingleHighDensityRouteStitchSolver extends BaseSolver { getSolverName(): string; mergedHdRoute: HighDensityIntraNodeRoute$1; remainingHdRoutes: HighDensityIntraNodeRoute$1[]; start: { x: number; y: number; z: number; }; end: { x: number; y: number; z: number; }; colorMap: Record; constructor(opts: { connectionName: string; hdRoutes: HighDensityIntraNodeRoute$1[]; start: { x: number; y: number; z: number; }; end: { x: number; y: number; z: number; }; colorMap?: Record; defaultTraceThickness?: number; defaultViaDiameter?: number; }); getDisjointedRoute(): { firstRoute: HighDensityIntraNodeRoute$1; }; _step(): void; visualize(): GraphicsObject; } type UnsolvedRoute = { connectionName: string; hdRoutes: HighDensityIntraNodeRoute$1[]; start: { x: number; y: number; z: number; }; end: { x: number; y: number; z: number; }; }; declare class MultipleHighDensityRouteStitchSolver extends BaseSolver { getSolverName(): string; unsolvedRoutes: UnsolvedRoute[]; activeSolver: SingleHighDensityRouteStitchSolver | null; mergedHdRoutes: HighDensityIntraNodeRoute$1[]; colorMap: Record; defaultTraceThickness: number; defaultViaDiameter: number; private getClosestEndpointHash; private selectRoutesAlongEndpointPath; constructor(params: { connections: SimpleRouteConnection[]; hdRoutes: HighDensityIntraNodeRoute$1[]; colorMap?: Record; layerCount: number; defaultViaDiameter?: number; }); _step(): void; visualize(): GraphicsObject; } /** * Merges same layer nodes into larger nodes. Pre-processing stage necessary * for "strawing". */ declare class SingleLayerNodeMergerSolver extends BaseSolver { getSolverName(): string; nodeMap: Map; currentBatchNodeIds: CapacityMeshNodeId[]; absorbedNodeIds: Set; nextBatchNodeIds: CapacityMeshNodeId[]; batchHadModifications: boolean; hasComputedAdjacentNodeIds: boolean; newNodes: CapacityMeshNode[]; constructor(nodes: CapacityMeshNode[]); computeAdjacentNodeIdsForFirstBatch(nodes: CapacityMeshNode[]): void; getAdjacentSameLayerUnprocessedNodes(rootNode: CapacityMeshNode): CapacityMeshNode[]; getAdjacentSameLayerUnprocessedNodes2(rootNode: CapacityMeshNode): CapacityMeshNode[]; _step(): void; visualize(): GraphicsObject; } declare class StrawSolver extends BaseSolver { getSolverName(): string; multiLayerNodes: CapacityMeshNode[]; strawNodes: CapacityMeshNode[]; skippedNodes: CapacityMeshNode[]; unprocessedNodes: CapacityMeshNode[]; strawSize: number; nodeIdCounter: number; constructor(params: { nodes: CapacityMeshNode[]; strawSize?: number; }); getCapacityOfMultiLayerNodesWithinBounds(bounds: { minX: number; maxX: number; minY: number; maxY: number; }): number; getSurroundingCapacities(node: CapacityMeshNode): { leftSurroundingCapacity: number; rightSurroundingCapacity: number; topSurroundingCapacity: number; bottomSurroundingCapacity: number; }; /** * Creates straw nodes from a single-layer node based on surrounding capacities */ createStrawsForNode(node: CapacityMeshNode): CapacityMeshNode[]; getResultNodes(): CapacityMeshNode[]; _step(): void; visualize(): GraphicsObject; } type Phase$1 = "via_removal" | "via_merging" | "path_simplification"; /** * TraceSimplificationSolver consolidates trace optimization by iteratively applying * via removal, via merging, and path simplification phases. It reduces redundant vias * and simplifies routing paths through configurable iterations. * * The solver operates in three alternating phases per iteration: * 1. "via_removal" - Removes unnecessary vias from routes using UselessViaRemovalSolver * 2. "via_merging" - Merges redundant vias on the same net using SameNetViaMergerSolver * 3. "path_simplification" - Simplifies routing paths using MultiSimplifiedPathSolver * * Each iteration consists of all phases executed sequentially. */ declare class TraceSimplificationSolver extends BaseSolver { private readonly simplificationConfig; getSolverName(): string; hdRoutes: HighDensityRoute$1[]; simplificationPipelineLoops: number; MAX_SIMPLIFICATION_PIPELINE_LOOPS: number; PHASE_ORDER: Phase$1[]; currentPhase: Phase$1; /** Callback to extract results from the active sub-solver */ extractResult: ((solver: BaseSolver) => HighDensityRoute$1[]) | null; /** Returns the simplified routes. This is the primary output of the solver. */ get simplifiedHdRoutes(): HighDensityRoute$1[]; /** * Creates a new TraceSimplificationSolver * @param simplificationConfig Configuration object containing: * - hdRoutes: Initial high-density routes to simplify * - obstacles: Board obstacles to avoid during simplification * - connMap: Connectivity map for routing validation * - colorMap: Mapping of net names to colors for visualization * - outline: Optional board outline boundary * - defaultViaDiameter: Default diameter for vias * - layerCount: Number of routing layers * - minTraceToPadEdgeClearance: Minimum trace-edge clearance to pads/vias * - iterations: Number of complete simplification iterations (default: 2) */ constructor(simplificationConfig: { readonly hdRoutes: ReadonlyArray; readonly obstacles: ReadonlyArray; readonly connMap: ConnectivityMap; readonly colorMap: Readonly>; readonly outline?: ReadonlyArray<{ x: number; y: number; }>; readonly defaultViaDiameter: number; readonly layerCount: number; readonly minTraceToPadEdgeClearance?: number; }); private isSameNetObstacle; private getSameNetObstacleForSegment; private isViaInsideSameNetObstacle; private markThroughObstacleSegments; _step(): void; visualize(): GraphicsObject; } /** * ObstacleTree wraps different spatial index implementations: * - 'native': original spatial-hash grid * - 'rbush': dynamic R-tree via rbush * - 'flatbush': static index via flatbush */ declare class ObstacleSpatialHashIndex { private idx; private storage; constructor(implementation?: "native" | "rbush" | "flatbush", obstacles?: Obstacle[]); insert(o: Obstacle): void; search(bbox: { minX: number; minY: number; maxX: number; maxY: number; }): Obstacle[]; searchArea(centerX: number, centerY: number, width: number, height: number): Obstacle[]; } interface Point$2 { x: number; y: number; z: number; } type HighDensityIntraNodeRoute = { connectionName: string; rootConnectionName?: string; traceThickness: number; viaDiameter: number; route: Array<{ x: number; y: number; z: number; insideJumperPad?: boolean; }>; vias: Array<{ x: number; y: number; }>; jumpers?: Jumper[]; }; type HighDensityRoute = HighDensityIntraNodeRoute; declare class HighDensityRouteSpatialIndex { private segmentBuckets; private viaBuckets; private CELL_SIZE; constructor(routes: HighDensityRoute[], cellSize?: number); /** * Finds routes that potentially conflict with a given line segment within a margin. * Checks both segments and vias. * @param segmentStart Start point of the query segment. * @param segmentEnd End point of the query segment. * @param margin The minimum required clearance distance from the query segment's centerline. * @returns An array of conflicting routes and their minimum distance to the segment. */ getConflictingRoutesForSegment(segmentStart: Point$2, // Keep Point for original Z data if needed elsewhere segmentEnd: Point$2, margin: number): Array<{ conflictingRoute: HighDensityRoute; distance: number; }>; /** * Removes a route from the spatial index by connection name. * @param connectionName The connection name of the route to remove. */ removeRoute(connectionName: string): void; /** * Adds a single route to the spatial index. * @param route The route to add. */ addRoute(route: HighDensityRoute): void; /** * Finds routes that pass near a given point within a margin. * Checks both segments and vias. * @param point The query point {x, y, z}. * @param margin The minimum required clearance distance from the query point. * @returns An array of conflicting routes and their minimum distance to the point. */ getConflictingRoutesNearPoint(point: Point3, margin: number): Array<{ conflictingRoute: HighDensityRoute; distance: number; }>; } interface Point2D$2 { x: number; y: number; } interface Point3D$1 extends Point2D$2 { z: number; } interface TraceWidthSolverInput { hdRoutes: HighDensityRoute$1[]; connection: SimpleRouteConnection[]; obstacles?: Obstacle[]; connMap?: ConnectivityMap; colorMap?: Record; minTraceWidth: number; obstacleMargin?: number; layerCount: number; } /** * TraceWidthSolver determines the optimal trace width for each route. * It uses a TRACE_WIDTH_SCHEDULE to try progressively narrower widths: * [nominalTraceWidth, (nominalTraceWidth + minTraceWidth)/2, minTraceWidth] * * For each trace, it walks along with a cursor checking clearance. * If clearance is insufficient for the current width, it tries the next * narrower width in the schedule. * * It only runs width adjustments for routes whose connection provides a * nominalTraceWidth; routes without one are passed through unchanged. * The schedule is built per-route from that connection's nominalTraceWidth. */ declare class TraceWidthSolver extends BaseSolver { getSolverName(): string; hdRoutes: HighDensityRoute$1[]; hdRoutesWithWidths: HighDensityRoute$1[]; nominalTraceWidth: number; minTraceWidth: number; obstacleMargin: number; TRACE_WIDTH_SCHEDULE: number[]; connectionNominalTraceWidthMap: Map; unprocessedRoutes: HighDensityRoute$1[]; processedRoutes: HighDensityRoute$1[]; currentTrace: HighDensityRoute$1 | null; cursorPosition: Point3D$1 | null; currentTraceSegmentIndex: number; currentTraceSegmentT: number; currentScheduleIndex: number; currentTargetWidth: number; hasInsufficientClearance: boolean; lastCollidingObstacles: Obstacle[]; lastCollidingRoutes: HighDensityRoute$1[]; lastClearance: number; obstacles: Obstacle[]; obstacleSHI?: ObstacleSpatialHashIndex; hdRouteSHI: HighDensityRouteSpatialIndex; connMap?: ConnectivityMap; colorMap?: Record; constructor(input: TraceWidthSolverInput); private getNominalTraceWidthForRoute; _step(): void; /** * Initializes/resets the cursor for processing a trace */ private initializeCursor; /** * Steps the cursor forward by CURSOR_STEP_DISTANCE along the trace * Returns false if we've reached the end of the trace * Skips segments where both endpoints are inside jumper pads */ private stepCursorForward; /** * Checks if an obstacle is a jumper pad belonging to the current trace's jumpers. * This is needed because jumper pads may not have connectedTo set properly. */ private isObstacleOwnJumperPad; /** * Gets the minimum clearance at a given position from obstacles and other traces * Also updates lastCollidingObstacles and lastCollidingRoutes for visualization */ private getClearanceAtPosition; private isObstacleOnPointLayer; private getAdjacentNonCoincidentRoutePoint; private getObstacleWidthAlongVector; private getTerminalPadWidthLimit; private getRouteDistanceInfo; private interpolateRoutePointAtDistance; private getTaperWidthAtDistance; private createTerminalTaperedRoute; private createRouteWithWidth; /** * Finalizes the current trace with the given width */ private finalizeCurrentTrace; visualize(): GraphicsObject; /** Returns the routes with determined widths. This is the primary output of the solver. */ getHdRoutesWithWidths(): HighDensityRoute$1[]; } interface CapacityMeshSolverOptions$9 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; } type PipelineStep$9 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AutoroutingPipelineSolver2_PortPointPathing) => ConstructorParameters; onSolved?: (instance: AutoroutingPipelineSolver2_PortPointPathing) => void; }; declare class AutoroutingPipelineSolver2_PortPointPathing extends BaseSolver { readonly srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$9; getSolverName(): string; netToPointPairsSolver?: NetToPointPairsSolver; nodeSolver?: RectDiffPipeline; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; colorMap: Record; highDensityRouteSolver?: HighDensitySolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; availableSegmentPointSolver?: AvailableSegmentPointSolver; portPointPathingSolver?: HyperPortPointPathingSolver; multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer; uniformPortDistributionSolver?: UniformPortDistributionSolver; traceWidthSolver?: TraceWidthSolver; viaDiameter: number; minTraceWidth: number; effort: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithPointPairs?: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; inputNodeWithPortPoints: InputNodeWithPortPoints[]; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9 | PipelineStep$9)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$9); getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$9]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; /** * A lightweight version of the visualize method that can be used to stream * progress * * We return the most relevant graphic for the stage: * 1. netToPointPairs output * 2. Capacity Planning Output * 3. High Density Route Solver Output, max 200 lines */ preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; /** * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces */ getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } /** @deprecated Use AutoroutingPipelineSolver instead */ declare const CapacityMeshSolver: typeof AutoroutingPipelineSolver2_PortPointPathing; type CapacityMeshSolver = AutoroutingPipelineSolver2_PortPointPathing; interface NodePortSegment { capacityMeshNodeId: string; nodePortSegmentId?: string; start: { x: number; y: number; }; end: { x: number; y: number; }; availableZ: number[]; connectionNames: string[]; rootConnectionNames?: string[]; } /** * Each Node is a square. The capacity paths indicate the nodes the trace will * travel through. We want to find the "Port Segment" that each capacity path * will take for each node. */ declare class CapacityEdgeToPortSegmentSolver extends BaseSolver { getSolverName(): string; nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; capacityPaths: CapacityPath[]; nodeMap: Map; nodeEdgeMap: Map; unprocessedNodeIds: CapacityMeshNodeId[]; nodePortSegments: Map; colorMap: Record; constructor({ nodes, edges, capacityPaths, colorMap, }: { nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; capacityPaths: CapacityPath[]; colorMap?: Record; }); step(): void; visualize(): GraphicsObject; } interface Target$1 { x: number; y: number; bounds: { minX: number; minY: number; maxX: number; maxY: number; }; connectionName: string; availableZ: number[]; } type BucketCoordinate$1 = `${number}x${number}`; declare class TargetTree { targets: Target$1[]; buckets: Map; CELL_SIZE: number; constructor(targets: Target$1[]); getBucketKey(x: number, y: number): BucketCoordinate$1; getTargetsInArea(centerX: number, centerY: number, width: number, height: number): Target$1[]; } interface CapacityMeshNodeSolverOptions$2 { capacityDepth?: number; } interface Target { x: number; y: number; bounds: { minX: number; minY: number; maxX: number; maxY: number; }; connectionName: string; availableZ: number[]; } declare class CapacityMeshNodeSolver extends BaseSolver { srj: SimpleRouteJson; opts: CapacityMeshNodeSolverOptions$2; getSolverName(): string; unfinishedNodes: CapacityMeshNode[]; finishedNodes: CapacityMeshNode[]; nodeToXYOverlappingObstaclesMap: Map; layerCount: number; protected outlinePolygon?: Polygon; MAX_DEPTH: number; targets: Target[]; targetTree: TargetTree; obstacleTree: ObstacleSpatialHashIndex; readonly obstacleZLayersByObstacle: WeakMap; constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions$2); computeTargets(): Target[]; protected getNodeBounds(node: CapacityMeshNode): { minX: number; maxX: number; minY: number; maxY: number; }; protected getNodeRect(node: CapacityMeshNode): { center: { x: number; y: number; }; width: number; height: number; }; _nextNodeCounter: number; getNextNodeId(): string; getCapacityFromDepth(depth: number): number; getTargetIfNodeContainsTarget(node: CapacityMeshNode): Target | null; getXYOverlappingObstacles(node: CapacityMeshNode): Obstacle[]; getXYZOverlappingObstacles(node: CapacityMeshNode): Obstacle[]; /** * Checks if the given mesh node overlaps with any obstacle. * We treat both obstacles and nodes as axis‐aligned rectangles. */ doesNodeOverlapObstacle(node: CapacityMeshNode): boolean; /** * Checks if the entire node is contained within any obstacle. */ isNodeCompletelyInsideObstacle(node: CapacityMeshNode): boolean; getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[]; shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean; _step(): void; /** * Creates a GraphicsObject to visualize the mesh, its nodes, obstacles, and connection points. * * - Mesh nodes are rendered as rectangles. * - Nodes that have an obstacle intersection are outlined in red. * - Other nodes are outlined in green. * - Lines are drawn from a node to its parent. * - Obstacles are drawn as semi-transparent red rectangles. * - Points for each connection’s pointsToConnect are drawn in a unique color. */ visualize(): GraphicsObject; private getObstacleZLayers; } interface CapacityMeshNodeSolverOptions$1 { capacityDepth?: number; } declare class CapacityMeshNodeSolver2_NodeUnderObstacle extends CapacityMeshNodeSolver { srj: SimpleRouteJson; opts: CapacityMeshNodeSolverOptions$1; getSolverName(): string; VIA_DIAMETER: number; OBSTACLE_MARGIN: number; /** * The threshold for the percentage of a single-layer node that must be * covered by obstacles to be considered "under an obstacle" */ OVERLAP_THRESHOLD_FOR_SINGLE_LAYER_NODES: number; constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions$1); isNodeCompletelyOutsideBounds(node: CapacityMeshNode): boolean; isNodePartiallyOutsideBounds(node: CapacityMeshNode): boolean; /** * Calculate the percentage of node area covered by obstacles */ getObstacleCoveragePercentage(node: CapacityMeshNode): number; /** * Check if a single-layer node should be filtered due to obstacle coverage */ shouldFilterSingleLayerNodeForObstacle(node: CapacityMeshNode): boolean; /** * Check if a node should be filtered due to obstacles. * Single-layer nodes: filtered only if >20% covered * Multi-layer nodes: filtered if any overlap */ shouldFilterNodeForObstacle(node: CapacityMeshNode): boolean; createChildNodeAtPosition(parent: CapacityMeshNode, opts: { center: { x: number; y: number; }; width: number; height: number; availableZ: number[]; _depth?: number; }): CapacityMeshNode; getZSubdivisionChildNodes(node: CapacityMeshNode): CapacityMeshNode[]; getChildNodes(parent: CapacityMeshNode): CapacityMeshNode[]; shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean; _step(): void; } interface SegmentWithAssignedPoints extends NodePortSegment { assignedPoints?: { connectionName: string; rootConnectionName?: string; point: { x: number; y: number; z: number; }; }[]; } /** * CapacitySegmentToPointSolver: * * In each step, the solver iterates over all unsolved segments (segments * without points assigned for each connection). For each segment: * * - If there is only one connection, it assigns the center as the point. * - If there are two connections, it attempts to determine the ordering using * other segments within the node. If no ordering can be determined, it does nothing. * * If an iteration produces no new assignments, the solver picks the segment with * the fewest connections and assigns points evenly spaced along the segment, * ordering them alphabetically. */ declare class CapacitySegmentToPointSolver extends BaseSolver { getSolverName(): string; unsolvedSegments: SegmentWithAssignedPoints[]; solvedSegments: (NodePortSegment & { assignedPoints: { connectionName: string; rootConnectionName?: string; point: { x: number; y: number; z: number; }; }[]; })[]; nodeMap: Record; colorMap: Record; constructor({ segments, colorMap, nodes, }: { segments: NodePortSegment[]; colorMap?: Record; /** * This isn't used by the algorithm, but allows associating metadata * for the result datatype (the center, width, height of the node) */ nodes: CapacityMeshNode[]; }); /** * Perform one iteration step. */ _step(): void; /** * Return the assigned points for each segment. */ getNodesWithPortPoints(): NodeWithPortPoints[]; /** * Return a GraphicsObject that visualizes the segments with assigned points. */ visualize(): GraphicsObject; } interface CapacityHyperParameters { VIA_DIAMETER: number; TRACE_WIDTH: number; MAX_CAPACITY_FACTOR: number; } type Candidate$2 = { prevCandidate: Candidate$2 | null; node: CapacityMeshNode; f: number; g: number; h: number; }; type ConnectionPathWithNodes$1 = { connection: SimpleRouteConnection; nodes: CapacityMeshNode[]; path?: CapacityMeshNode[]; straightLineDistance: number; }; declare class CapacityPathingSolver extends BaseSolver { getSolverName(): string; connectionsWithNodes: Array; usedNodeCapacityMap: Map; simpleRouteJson: SimpleRouteJson; nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; GREEDY_MULTIPLIER: number; MAX_CANDIDATES_IN_MEMORY: number; nodeMap: Map; nodeEdgeMap: Map; connectionNameToGoalNodeIds: Map; colorMap: Record; maxDepthOfNodes: number; activeCandidateStraightLineDistance?: number; debug_lastNodeCostMap: Map; hyperParameters: Partial; constructor({ simpleRouteJson, nodes, edges, colorMap, MAX_ITERATIONS, hyperParameters, }: { simpleRouteJson: SimpleRouteJson; nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; colorMap?: Record; MAX_ITERATIONS?: number; hyperParameters?: Partial; }); getTotalCapacity(node: CapacityMeshNode): number; getConnectionsWithNodes(): { connectionsWithNodes: { connection: SimpleRouteConnection; nodes: CapacityMeshNode[]; pathFound: boolean; straightLineDistance: number; }[]; connectionNameToGoalNodeIds: Map; }; currentConnectionIndex: number; candidates?: Array | null; visitedNodes?: Set | null; computeG(prevCandidate: Candidate$2, node: CapacityMeshNode, endGoal: CapacityMeshNode): number; computeH(prevCandidate: Candidate$2, node: CapacityMeshNode, endGoal: CapacityMeshNode): number; getBacktrackedPath(candidate: Candidate$2): CapacityMeshNode[]; getNeighboringNodes(node: CapacityMeshNode): CapacityMeshNode[]; getCapacityPaths(): CapacityPath[]; doesNodeHaveCapacityForTrace(node: CapacityMeshNode, prevNode: CapacityMeshNode): boolean; canTravelThroughObstacle(node: CapacityMeshNode, connectionName: string): boolean; getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode): number; reduceCapacityAlongPath(nextConnection: { path?: CapacityMeshNode[]; }): void; isConnectedToEndGoal(node: CapacityMeshNode, endGoal: CapacityMeshNode): boolean; _step(): void; visualize(): GraphicsObject; } declare class CapacityPathingSolver5 extends CapacityPathingSolver { getSolverName(): string; NEGATIVE_CAPACITY_PENALTY_FACTOR: number; REDUCED_CAPACITY_PENALTY_FACTOR: number; constructor(...args: ConstructorParameters); get maxCapacityFactor(): number; getTotalCapacity(node: CapacityMeshNode): number; /** * Penalty you pay for using this node */ getNodeCapacityPenalty(node: CapacityMeshNode): number; /** * We're rewarding travel into big nodes. * * To minimize shortest path, you'd want to comment this out. */ getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode): number; computeG(prevCandidate: Candidate$2, node: CapacityMeshNode, endGoal: CapacityMeshNode): number; computeH(prevCandidate: Candidate$2, node: CapacityMeshNode, endGoal: CapacityMeshNode): number; } declare class CapacityPathingGreedySolver extends CapacityPathingSolver5 { getSolverName(): string; doesNodeHaveCapacityForTrace(node: CapacityMeshNode, prevNode: CapacityMeshNode): boolean; getNodeCapacityPenalty(node: CapacityMeshNode): number; } type Candidate$1 = { prevCandidate: Candidate$1 | null; node: CapacityMeshNode; f: number; g: number; h: number; }; interface CpssPathingSolverHyperParameters { SHUFFLE_SEED?: number; EXPANSION_DEGREES?: number; } interface CapacityPathingSingleSectionPathingSolverParams { sectionNodes: CapacityMeshNode[]; sectionEdges: CapacityMeshEdge[]; sectionConnectionTerminals: Array<{ connectionName: string; startNodeId: CapacityMeshNodeId; endNodeId: CapacityMeshNodeId; }>; colorMap?: Record; centerNodeId: string; nodeMap?: Map; nodeEdgeMap?: Map; hyperParameters?: CpssPathingSolverHyperParameters; } declare class CapacityPathingSingleSectionSolver extends BaseSolver { getSolverName(): string; GREEDY_MULTIPLIER: number; sectionNodes: CapacityMeshNode[]; sectionEdges: CapacityMeshEdge[]; sectionConnectionTerminals: Array<{ connectionName: string; startNodeId: CapacityMeshNodeId; endNodeId: CapacityMeshNodeId; path?: CapacityMeshNode[]; }>; nodeMap: Map; nodeEdgeMap: Map; colorMap: Record; usedNodeCapacityMap: Map; totalNodeCapacityMap: Map; centerNodeId: string; private currentSectionScore; MAX_CANDIDATES_IN_MEMORY: number; currentConnectionIndex: number; candidates?: Array | null; visitedNodes?: Set | null; queuedNodes?: Set | null; activeCandidateStraightLineDistance?: number; debug_lastNodeCostMap: Map; maxCapacityFactor: number; constructor(params: CapacityPathingSingleSectionPathingSolverParams); getTotalCapacity(node: CapacityMeshNode): number; getNodeCapacityPenalty(node: CapacityMeshNode): number; getDistanceBetweenNodes(A: CapacityMeshNode, B: CapacityMeshNode): number; computeG(prevCandidate: Candidate$1, node: CapacityMeshNode, endGoal: CapacityMeshNode): number; computeH(prevCandidate: Candidate$1, // prevCandidate not strictly needed here node: CapacityMeshNode, endGoal: CapacityMeshNode): number; getBacktrackedPath(candidate: Candidate$1): CapacityMeshNode[]; getNeighboringNodes(node: CapacityMeshNode): CapacityMeshNode[]; isConnectedToEndGoal(node: CapacityMeshNode, endGoal: CapacityMeshNode): boolean; doesNodeHaveCapacityForTrace(node: CapacityMeshNode, prevNode: CapacityMeshNode | null): boolean; reduceCapacityAlongPath(path: CapacityMeshNode[]): void; getSolvedSectionScore(): number; _step(): void; computeProgress(): number; private _setupAStar; private _handleCandidatesExhausted; private _handleGoalReached; visualize(): GraphicsObject; } declare const CapacityPathingSingleSectionPathingSolver: typeof CapacityPathingSingleSectionSolver; type CapacityPathingSingleSectionPathingSolver = InstanceType; declare class HyperCapacityPathingSingleSectionSolver extends HyperParameterSupervisorSolver { getSolverName(): string; constructorParams: CapacityPathingSingleSectionPathingSolverParams; winningSolver?: CapacityPathingSingleSectionPathingSolver; constructor(params: ConstructorParameters[0]); computeG(solver: CapacityPathingSingleSectionPathingSolver): number; computeH(solver: CapacityPathingSingleSectionPathingSolver): number; getCombinationDefs(): Array> | null; getFailureMessage(): string; getHyperParameterDefs(): Array; generateSolver(hyperParameters: any): CapacityPathingSingleSectionPathingSolver; onSolve({ solver, }: SupervisedSolver): void; get centerNodeId(): string; get sectionNodes(): CapacityMeshNode[]; get sectionConnectionTerminals(): { connectionName: string; startNodeId: CapacityMeshNodeId; endNodeId: CapacityMeshNodeId; path?: CapacityMeshNode[]; }[] | undefined; } interface SectionConnectionTerminal { connectionName: string; startNodeId: CapacityMeshNodeId; endNodeId: CapacityMeshNodeId; path?: CapacityMeshNode[]; } interface CapacityPathingSection { centerNodeId: string; sectionConnectionTerminals: SectionConnectionTerminal[]; sectionNodes: CapacityMeshNode[]; sectionEdges: CapacityMeshEdge[]; } type CapacityMeshEdgeId = string; /** * This solver solves for capacity paths by first solving with negative * capacities allowed, then re-solving problematic sections with a section * solver. */ declare class CapacityPathingMultiSectionSolver extends BaseSolver { getSolverName(): string; simpleRouteJson: SimpleRouteJson; nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; nodeEdgeMap: Map; connectionsWithNodes: Array; colorMap: Record; initialSolver: CapacityPathingGreedySolver; cacheProvider?: CacheProvider | null; stage: "initialization" | "section-optimization"; nodeMap: Map; allNodeIdsSet: Set; usedNodeCapacityMap: Map; totalNodeCapacityMap: Map; nodeCapacityPercentMap: Map; nodeOptimizationAttemptCountMap: Map; currentSection: CapacityPathingSection | null; sectionSolver?: CapacityPathingSingleSectionSolver | HyperCapacityPathingSingleSectionSolver | null; currentScheduleIndex: number; stats: { successfulOptimizations: number; failedOptimizations: number; failedSectionSolvers: number; startingScore: number; scheduleScores: Array<{ maxExpansionDegrees: number; sectionAttempts: number; endingScore: number; endingHighestNodePf: number; }>; cacheHits: number; cacheMisses: number; }; OPTIMIZATION_SCHEDULE: { MAX_ATTEMPTS_PER_NODE: number; MAX_EXPANSION_DEGREES: number; MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: number; }[]; get currentSchedule(): { MAX_ATTEMPTS_PER_NODE: number; MAX_EXPANSION_DEGREES: number; MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: number; }; constructor(params: ConstructorParameters[0] & { initialPathingSolver?: CapacityPathingGreedySolver; cacheProvider?: CacheProvider | null; }); _stepInitialization(): void; _getNextNodeToOptimize(): CapacityMeshNodeId | null; getOverallScore(): { highestNodePf: number; score: number; }; _stepSectionOptimization(): void; /** * Merges the paths found by a successful section solver back into the main * connectionsWithNodes list. */ private _mergeSolvedSectionPaths; /** * Recalculates node capacity usage based on the current connectionsWithNodes * and updates the nodeCapacityPercentMap. */ private _recalculateNodeCapacityUsage; getCapacityPaths(): CapacityPath[]; _step(): void; visualize(): graphics_debug.GraphicsObject; } type NodePortSegmentId = string; interface ChangeLayerOperation { op: "changeLayer"; segmentId: string; pointIndex: number; newLayer: number; /** Operation is mutated and oldLayer is added to allow reversal */ oldLayer?: number; cost?: number; } interface SwitchOperation { op: "switch"; segmentId: string; point1Index: number; point2Index: number; cost?: number; } interface CombinedOperation { op: "combined"; subOperations: Array; cost?: number; } type Operation = ChangeLayerOperation | SwitchOperation | CombinedOperation; /** * Use simulated annealing to try to improve the placement of points (via * swapping with points on the same segment) or changing the layer. * * We have the following pieces of information: * - NodePortSegment with nodePortSegmentId * - A "neighbor" NodePortSegmentWithAssignedPoints has one change * - A change can be flipping a point to the opposite layer * - A change can also be switching the position of two points * - We represent the operations used to change from an original scene * with a list of operations [SEG1_CL(1, 1), SEG1_SW(1, 2), SEG2_CL(2, 0)] * - CN indicates the capacity node to edit * - The SW operation "switches" the x/y location of two points * - The CL operation changes the layer of the point * - When choosing edits to make, we are biased to operate on nodes that have a * high cost and biased against operating on nodes we've operated on a lot * - Each step, we generate an operation and use the standard simulated * annealing function to determine if we should perform the operation */ declare class CapacitySegmentPointOptimizer extends BaseSolver { getSolverName(): string; assignedSegments: SegmentWithAssignedPoints[]; colorMap: Record; nodeMap: Map; nodeIdToSegmentIds: Map; segmentIdToNodeIds: Map; currentMutatedSegments: Map; allSegmentIds: string[]; lastAppliedOperation: Operation | null; lastCreatedOperation: Operation | null; currentNodeCosts: Map; lastAcceptedIteration: number; currentCost: number; randomSeed: number; numNodes: number; probabilityOfFailure: number; nodesThatCantFitVias: Set; mutableSegments: Set; VIA_DIAMETER: number; OBSTACLE_MARGIN: number; MAX_OPERATIONS_PER_MUTATION: number; MAX_NODE_CHAIN_PER_MUTATION: number; NOOP_ITERATIONS_BEFORE_EARLY_STOP: number; constructor({ assignedSegments, colorMap, nodes, viaDiameter, }: { assignedSegments: NodePortSegment[]; colorMap?: Record; /** * This isn't used by the algorithm, but allows associating metadata * for the result datatype (the center, width, height of the node) */ nodes: CapacityMeshNode[]; viaDiameter?: number; }); random(): number; /** * The cost is the "probability of failure" of the node. */ computeNodeCost(nodeId: CapacityMeshNodeId): number; /** * Number of traces that can go through this node if they are completely * straight without crossings */ getUsedTraceCapacity(nodeId: CapacityMeshNodeId): number; /** * Granular via capacity is a consideration of capacity that includes... * - The number of traces * - The number of trace crossings (0-2 vias per trace crossing) * - Empirically, each crossing typically results in 0.82 vias * - e.g. 17 traces would typically have 51 crossings & 42 vias * - The number of layer changes (at least 1 via per layer change) * - We don't know how a entry/exit being on separated layers effects * the capacity/number of vias yet * * - Generally minimizing the number of crossings is pretty good, if there * is no trace crossing you basically don't have any used capacity * - If the entry/exit layer is different, you're guaranteed to have at least * one via * * - Total capacity is computed by estimating the number of vias that could * be created using the formula (viaFitAcross / 2) ** 1.1 */ getUsedViaCapacity(nodeId: CapacityMeshNodeId): number; getRandomWeightedNodeId(): CapacityMeshNodeId; getRandomWeightedSegmentId(): string; getMutableSegments(): Set; isSegmentMutable(segmentId: string): boolean; getRandomOperationForSegment(randomSegmentId: string): SwitchOperation | ChangeLayerOperation | null; getNodesNearNode(nodeId: CapacityMeshNodeId, hops?: number): CapacityMeshNodeId[]; getRandomCombinedOperationNearNode(nodeId: CapacityMeshNodeId): CombinedOperation; /** * A combined operation can perform multiple operations on a single node, this * allows it to reach outcomes that may not be beneficial with since * operations */ getRandomCombinedOperationOnSingleNode(max?: number): CombinedOperation; getRandomOperation(): Operation; /** * We compute "overall probability of failure" as our overall cost, then * linearize it to make it easier to work with */ computeCurrentCost(): { cost: number; nodeCosts: Map; probabilityOfFailure: number; linearizedCost: number; }; applyOperation(op: Operation): void; reverseOperation(op: Operation): void; isNewCostAcceptable(oldPf: number, newPf: number): boolean; /** * FOR OUTPUT: Return the assigned points for each segment. */ getNodesWithPortPoints(): NodeWithPortPoints[]; _step(): void; visualize(): GraphicsObject; } /** * A simplified version of MultipleHighDensityRouteStitchSolver that doesn't handle * off-board routing cases. It always uses the connection's pointsToConnect directly * instead of analyzing possible endpoints from route islands. */ declare class NoOffBoardMultipleHighDensityRouteStitchSolver extends MultipleHighDensityRouteStitchSolver { getSolverName(): string; constructor(params: { connections: SimpleRouteConnection[]; hdRoutes: any[]; colorMap?: Record; layerCount: number; defaultViaDiameter?: number; }); } type SegmentPointId = string; type SegmentId = string; interface BaseUnravelIssue { probabilityOfFailure: number; } interface UnravelTransitionViaIssue extends BaseUnravelIssue { type: "transition_via"; capacityMeshNodeId: CapacityMeshNodeId; segmentPoints: SegmentPointId[]; } interface UnravelSameLayerCrossingIssue extends BaseUnravelIssue { type: "same_layer_crossing"; capacityMeshNodeId: CapacityMeshNodeId; crossingLine1: [SegmentPointId, SegmentPointId]; crossingLine2: [SegmentPointId, SegmentPointId]; } interface UnravelSingleTransitionCrossingIssue extends BaseUnravelIssue { type: "single_transition_crossing"; capacityMeshNodeId: CapacityMeshNodeId; sameLayerCrossingLine: [SegmentPointId, SegmentPointId]; transitionCrossingLine: [SegmentPointId, SegmentPointId]; } interface UnravelDoubleTransitionCrossingIssue extends BaseUnravelIssue { type: "double_transition_crossing"; capacityMeshNodeId: CapacityMeshNodeId; crossingLine1: [SegmentPointId, SegmentPointId]; crossingLine2: [SegmentPointId, SegmentPointId]; } interface UnravelTraceCapacityIssue extends BaseUnravelIssue { type: "same_layer_trace_imbalance_with_low_capacity"; capacityMeshNodeId: CapacityMeshNodeId; z: number; tracesOnLayer: Array<{ A: SegmentPointId; B: SegmentPointId; }>; } interface SegmentPoint { segmentPointId: SegmentPointId; directlyConnectedSegmentPointIds: SegmentPointId[]; connectionName: string; rootConnectionName?: string; segmentId: string; capacityMeshNodeIds: CapacityMeshNodeId[]; x: number; y: number; z: number; } type SegmentPointMap = Map; type UnravelIssue = UnravelTransitionViaIssue | UnravelSameLayerCrossingIssue | UnravelSingleTransitionCrossingIssue | UnravelDoubleTransitionCrossingIssue | UnravelTraceCapacityIssue; interface UnravelSection { allNodeIds: CapacityMeshNodeId[]; mutableNodeIds: CapacityMeshNodeId[]; mutableSegmentIds: Set; immutableNodeIds: CapacityMeshNodeId[]; segmentPointMap: SegmentPointMap; mutableSegmentPointIds: Set; zLockedSegmentPointIds: Set; segmentPairsInNode: Map>; segmentPointsInNode: Map; segmentPointsInSegment: Map; originalPointMap: Map; } interface UnravelChangeLayerOperation { type: "change_layer"; newZ: number; segmentPointIds: SegmentPointId[]; } interface UnravelSwapPositionOnSegmentOperation { type: "swap_position_on_segment"; segmentPointIds: SegmentPointId[]; } interface UnravelCombinedOperation { type: "combined"; operations: Array; } type UnravelOperation = UnravelChangeLayerOperation | UnravelSwapPositionOnSegmentOperation | UnravelCombinedOperation; type UnravelCandidate = { operationsPerformed: number; /** * A hash of the pointModifications to know if this candidate has already been * explored */ candidateHash: string; /** * More expensive hash that includes original positions */ candidateFullHash?: string; pointModifications: Map; issues: UnravelIssue[]; /** * The cost of this candidate (log probability of failure) considering all of * the point modifications */ g: number; /** * The estimated cost of this candidate (log probability of failure). We don't * currently know how to compute this so it's always 0. */ h: number; /** * Candidate cost ~(g + h) */ f: number; }; type SegmentPointMapAndReverseMaps = { segmentPointMap: SegmentPointMap; nodeToSegmentPointMap: Map; segmentToSegmentPointMap: Map; }; interface UnravelSectionHyperParameters { MAX_ITERATIONS_WITHOUT_IMPROVEMENT: number; } interface UnravelSectionSolverParams { rootNodeId: CapacityMeshNodeId; colorMap?: Record; MUTABLE_HOPS?: number; nodeMap: Map; dedupedSegments: SegmentWithAssignedPoints[]; dedupedSegmentMap?: Map; nodeIdToSegmentIds: Map; segmentIdToNodeIds: Map; segmentPointMap?: SegmentPointMap; nodeToSegmentPointMap?: Map; segmentToSegmentPointMap?: Map; hyperParameters?: Partial; } /** * The UntangleSectionSolver optimizes a section of connected capacity nodes * with their deduplicated segments. * * The section always has a "root" node. From the root node, MUTABLE_HOPS are * taken to reach other nodes that are mutable. One additional hop is taken to * have all the impacted nodes in section. So a section is composed of mutable * and immutable nodes. * * The goal of the solver is to perform operations on the mutable nodes of the * section to lower the overall cost of the section. * * The untangle phase will perform "operations" on segments based on "issues" * * An "issue" is anything that increases the cost of the node: * - Anything that causes a via (e.g. layer transition) * - Any time two traces cross on the same layer * * An operation is a change to a segment. There are two main operations: * - Change layer * - Change point order on segment * * This solver works by exploring different paths of operations. When an * operation is performed, new issues are created. Each path has a cost, and * a set of neighbors representing next operations to perform. * */ declare class UnravelSectionSolver extends BaseSolver { getSolverName(): string; nodeMap: Map; dedupedSegments: SegmentWithAssignedPoints[]; dedupedSegmentMap: Map; MUTABLE_HOPS: number; unravelSection: UnravelSection; candidates: UnravelCandidate[]; lastProcessedCandidate: UnravelCandidate | null; bestCandidate: UnravelCandidate | null; originalCandidate: UnravelCandidate; rootNodeId: CapacityMeshNodeId; nodeIdToSegmentIds: Map; segmentIdToNodeIds: Map; colorMap: Record; tunedNodeCapacityMap: Map; MAX_CANDIDATES: number; iterationsSinceImprovement: number; hyperParameters: UnravelSectionHyperParameters; selectedCandidateIndex: number | "best" | "original" | null; queuedOrExploredCandidatePointModificationHashes: Set; constructorParams: UnravelSectionSolverParams; constructor(params: UnravelSectionSolverParams); getConstructorParams(): UnravelSectionSolverParams; createUnravelSection(largeSpMaps?: SegmentPointMapAndReverseMaps): UnravelSection; createInitialCandidate(): UnravelCandidate; get nextCandidate(): UnravelCandidate | null; getPointInCandidate(candidate: UnravelCandidate, segmentPointId: SegmentPointId): { x: number; y: number; z: number; segmentId: string; }; /** * Get all segment points in the section that belong to a given connection. * This is used to propose layer changes for the entire connection path * when all endpoints are MLCPs (multi-layer connection points). */ getConnectionSegmentPointIds(connectionName: string): SegmentPointId[]; /** * Check if all segment points for a connection can use a given z layer. * Returns true if all segments have the target z in their availableZ. */ canConnectionUseLayer(connectionSegmentPointIds: SegmentPointId[], targetZ: number): boolean; getOperationsForIssue(candidate: UnravelCandidate, issue: UnravelIssue): UnravelOperation[]; computeG(params: { issues: UnravelIssue[]; originalCandidate: UnravelCandidate; operationsPerformed: number; operation: UnravelOperation; }): number; getUnexploredNeighborByApplyingOperation(currentCandidate: UnravelCandidate, operation: UnravelOperation): UnravelCandidate | null; getNeighborOperationsForCandidate(candidate: UnravelCandidate): UnravelOperation[]; getNeighbors(candidate: UnravelCandidate): UnravelCandidate[]; _step(): void; visualize(): GraphicsObject; } declare class UnravelMultiSectionSolver extends BaseSolver { getSolverName(): string; nodeMap: Map; dedupedSegmentMap: Map; dedupedSegments: SegmentWithAssignedPoints[]; nodeIdToSegmentIds: Map; segmentIdToNodeIds: Map; nodeToSegmentPointMap: Map; segmentToSegmentPointMap: Map; colorMap: Record; tunedNodeCapacityMap: Map; MAX_NODE_ATTEMPTS: number; MUTABLE_HOPS: number; ACCEPTABLE_PF: number; MAX_ITERATIONS_WITHOUT_IMPROVEMENT: number; /** * Probability of failure for each node */ nodePfMap: Map; attemptsToFixNode: Map; activeSubSolver: UnravelSectionSolver | null; segmentPointMap: SegmentPointMap; cacheProvider: CacheProvider | null; constructor({ assignedSegments, colorMap, nodes, cacheProvider, }: { assignedSegments: NodePortSegment[]; colorMap?: Record; /** * This isn't used by the algorithm, but allows associating metadata * for the result datatype (the center, width, height of the node) */ nodes: CapacityMeshNode[]; cacheProvider?: CacheProvider | null; }); computeInitialPfMap(): Map; computeNodePf(node: CapacityMeshNode): number; _step(): void; visualize(): GraphicsObject; getNodesWithPortPoints(): NodeWithPortPoints[]; } interface CapacityMeshSolverOptions$8 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; } type PipelineStep$8 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AutoroutingPipeline1_OriginalUnravel) => ConstructorParameters; onSolved?: (instance: AutoroutingPipeline1_OriginalUnravel) => void; }; declare class AutoroutingPipeline1_OriginalUnravel extends BaseSolver { readonly srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$8; getSolverName(): string; netToPointPairsSolver?: NetToPointPairsSolver; nodeSolver?: CapacityMeshNodeSolver; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; initialPathingSolver?: CapacityPathingGreedySolver; pathingOptimizer?: CapacityPathingMultiSectionSolver; edgeToPortSegmentSolver?: CapacityEdgeToPortSegmentSolver; colorMap: Record; segmentToPointSolver?: CapacitySegmentToPointSolver; unravelMultiSectionSolver?: UnravelMultiSectionSolver; segmentToPointOptimizer?: CapacitySegmentPointOptimizer; highDensityRouteSolver?: HighDensitySolver; highDensityStitchSolver?: NoOffBoardMultipleHighDensityRouteStitchSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; viaDiameter: number; minTraceWidth: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithPointPairs?: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8 | PipelineStep$8)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$8); getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$8]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; /** * A lightweight version of the visualize method that can be used to stream * progress * * We return the most relevant graphic for the stage: * 1. netToPointPairs output * 2. Capacity Planning Output * 3. High Density Route Solver Output, max 200 lines */ preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; /** * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces */ getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } interface Point2D$1 { x: number; y: number; } interface Segment { start: Point2D$1; end: Point2D$1; } interface Point2D { x: number; y: number; } interface Point3D extends Point2D { z: number; insideJumperPad?: boolean; } interface TraceKeepoutSolverInput { hdRoutes: HighDensityRoute$1[]; obstacles: Obstacle[]; /** SRJ Jumpers with pre-computed pad obstacles. These will be added to the obstacle index. */ jumpers?: Jumper$1[]; connMap: ConnectivityMap; colorMap: Record; keepoutRadiusSchedule?: number[]; srj?: Pick; } /** * TraceKeepoutSolver adjusts traces to maintain keepout distance from obstacles * and non-connected traces. It works by walking along each trace with a cursor, * detecting obstacles within a keepout radius, and pushing the draw position * orthogonally to avoid them. * * The solver processes traces through multiple passes with decreasing keepout * radii as defined by KEEPOUT_RADIUS_SCHEDULE. */ declare class TraceKeepoutSolver extends BaseSolver { private input; getSolverName(): string; originalHdRoutes: HighDensityRoute$1[]; hdRoutes: HighDensityRoute$1[]; redrawnHdRoutes: HighDensityRoute$1[]; KEEPOUT_RADIUS_SCHEDULE: number[]; currentScheduleIndex: number; currentKeepoutRadius: number; unprocessedRoutes: HighDensityRoute$1[]; smoothedCursorRoutes: HighDensityRoute$1[]; processedRoutes: HighDensityRoute$1[]; currentTrace: HighDensityRoute$1 | null; cursorPosition: Point3D | null; lastCursorPosition: Point3D | null; drawPosition: Point2D | null; currentTraceSegmentIndex: number; currentTraceSegmentT: number; recordedDrawPositions: Point3D[]; lastCollidingSegments: Segment[]; /** Maps segment index to the jumper that occupies that segment */ currentTraceJumperSegments: Map; obstacleSHI: ObstacleSpatialHashIndex; hdRouteSHI: HighDensityRouteSpatialIndex; boardOutlineRoutes: HighDensityRoute$1[]; constructor(input: TraceKeepoutSolverInput); getSmoothDistance(): number; /** * Extracts pad obstacles from the passed-in SRJ jumpers. * The pads already have connectedTo set based on which routes use each jumper. */ private getJumperPadObstacles; /** * Builds a map from segment index to the jumper that occupies that segment. * A segment is considered a jumper segment if it connects points near the * jumper's start and end positions. * * Uses a larger tolerance for matching because routes may be modified during * collision avoidance passes, but we still need to find the segment that * represents each jumper. */ private buildJumperSegmentMap; _step(): void; getStepDistance(): number; /** * Check if we're about to enter a jumper segment. * Returns the jumper if we're at the start of a jumper segment (T=0), null otherwise. */ private getJumperAtCurrentSegmentStart; /** * Steps the cursor forward by CURSOR_STEP_DISTANCE along the trace * Returns: "stepped" if normal step, "end" if reached end, "jumper" if crossed a jumper */ private stepCursorForward; /** * Gets all colliding segments (obstacle edges and trace outlines) within the keepout radius */ private getCollidingSegments; positionHasCollision(position: { x: number; y: number; z: number; }, margin?: number): boolean; /** * Checks if a new segment would intersect with any route from unprocessedRoutes, * smoothedCursorRoutes, or processedRoutes (excluding routes with the same connection name). */ private segmentIntersectsOtherRoutes; /** * Finalizes the current trace with the recorded draw positions */ private finalizeCurrentTrace; /** * Checks if a point is a jumper endpoint. */ private isJumperEndpoint; /** * Simplifies the route by removing collinear points, but preserves * jumper endpoints which must remain fixed. */ private simplifyRoute; /** * Creates artificial hdRoutes representing the board outline. * These routes act as obstacles to prevent traces from being pushed outside the board. */ private createBoardOutlineRoutes; visualize(): GraphicsObject; /** Returns the redrawn routes. This is the primary output of the solver. */ getRedrawnHdRoutes(): HighDensityRoute$1[]; } interface AdjacentObstacle { minX: number; minY: number; maxX: number; maxY: number; networkId?: string; } interface CurvyIntraNodeSolverParams { nodeWithPortPoints: NodeWithPortPoints; colorMap?: Record; traceWidth?: number; viaDiameter?: number; /** Obstacles from adjacent/solved nodes that might affect routing */ adjacentObstacles?: AdjacentObstacle[]; } /** * A solver that uses CurvyTraceSolver to create curved traces within a node. * It converts port points to waypoint pairs and generates smooth curved traces * that maximize distance between traces and obstacles. */ declare class CurvyIntraNodeSolver extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; colorMap: Record; traceWidth: number; viaDiameter: number; adjacentObstacles: AdjacentObstacle[]; routes: HighDensityIntraNodeRoute$1[]; curvyTraceSolver?: CurvyTraceSolver; phase: "initializing" | "solving" | "done"; constructor(params: CurvyIntraNodeSolverParams); _step(): void; _initializeCurvySolver(): void; _stepCurvySolver(): void; _convertOutputTraces(): void; getConstructorParams(): CurvyIntraNodeSolverParams; visualize(): GraphicsObject; } interface JumperPrepatternSolver2HyperParameters { /** Number of columns in the jumper grid */ COLS?: number; /** Number of rows in the jumper grid */ ROWS?: number; /** Orientation of jumpers - "horizontal" or "vertical" */ ORIENTATION?: "horizontal" | "vertical"; /** Jumper type - "1206x4" or "0603". Defaults to "1206x4" */ JUMPER_TYPE?: JumperType; /** Number of traces to reserve space for between adjacent jumpers (0603 only) */ TRACE_CHANNELS_BETWEEN_JUMPERS?: number; /** 0603 topology pattern. Defaults to "grid" */ PATTERN?: "grid" | "staggered"; } interface JumperPrepatternSolver2Params { nodeWithPortPoints: NodeWithPortPoints; colorMap?: Record; traceWidth?: number; obstacleMargin?: number; hyperParameters?: JumperPrepatternSolver2HyperParameters; connMap?: ConnectivityMap; } interface XYConnection { start: { x: number; y: number; }; end: { x: number; y: number; }; connectionId: string; } declare class JumperPrepatternSolver2_HyperGraph extends BaseSolver { getSolverName(): string; constructorParams: JumperPrepatternSolver2Params; nodeWithPortPoints: NodeWithPortPoints; colorMap: Record; traceWidth: number; obstacleMargin: number; hyperParameters: JumperPrepatternSolver2HyperParameters; jumperGraphSolver: JumperGraphSolver | null; xyConnections: XYConnection[]; graphBounds: { minX: number; maxX: number; minY: number; maxY: number; } | null; jumperLocations: Array<{ center: { x: number; y: number; }; orientation: "vertical" | "horizontal"; padRegions: JRegion[]; }>; solvedRoutes: HighDensityIntraNodeRouteWithJumpers[]; jumpers: Jumper$1[]; phase: "jumperGraph" | "curvyTrace" | "done"; curvySolvers: Array<{ solver: CurvyTraceSolver; regionId: string; traversals: Array<{ routeIndex: number; connectionName: string; rootConnectionName?: string; }>; }>; currentCurvySolverIndex: number; routeInfos: Array<{ connectionId: string; rootConnectionName?: string; jumpers: Jumper[]; traversals: Array<{ regionId: string; region: JRegion; entryPort: JPort; exitPort: JPort | null; }>; }>; regionCurvedPaths: Map; start: { x: number; y: number; }; end: { x: number; y: number; }; }>>>; constructor(params: JumperPrepatternSolver2Params); getConstructorParams(): JumperPrepatternSolver2Params; private _buildColorMap; private _normalizeRegionPolygonsToBounds; private _getPatternConfig; /** * Generate a 0603 jumper grid sized to fit the node bounds. * generateJumperGrid doesn't support bounds/orientation, so we calculate * the outer padding dynamically to ensure the grid extends to the node boundaries. * NO SCALING - the outer padding is calculated to fill the space. */ private _generate0603Grid; private _initializeGraph; _step(): void; private _stepJumperGraph; private _stepCurvyTrace; /** * Initialize CurvyTraceSolvers for each routing region. * Called after JumperGraphSolver completes to set up the curvy trace phase. */ private _initializeCurvyTraceSolvers; /** * Finalize results after all CurvyTraceSolvers have completed. * Assembles final routes using curved paths where available. */ private _finalizeCurvyTraceResults; getOutput(): HighDensityIntraNodeRouteWithJumpers[]; /** * Returns all jumpers from the baseGraph as SRJ Jumper objects. * The pads have connectedTo set based on which routes use each jumper. * Must be called after the solver is solved. */ getOutputJumpers(): Jumper$1[]; visualize(): GraphicsObject; private _drawJumperPads; } interface HyperJumperPrepatternSolver2Params { nodeWithPortPoints: NodeWithPortPoints; colorMap?: Record; traceWidth?: number; obstacleMargin?: number; connMap?: ConnectivityMap; hyperParameters?: JumperPrepatternSolver2HyperParameters; /** Available jumper types. Defaults to ["0603"] */ availableJumperTypes?: JumperType[]; } type VariantHyperParameters = { COLS: number; ROWS: number; ORIENTATION: "horizontal" | "vertical"; JUMPER_TYPE: JumperType; PATTERN?: "grid" | "staggered"; TRACE_CHANNELS_BETWEEN_JUMPERS?: number; }; /** * HyperJumperPrepatternSolver2 runs multiple variants of JumperPrepatternSolver2_HyperGraph * with different pattern types and orientations, then picks the best solution. * * Variants: * - single_1206x4_vertical * - single_1206x4_horizontal * - 2x2_1206x4_vertical (only if node is large enough, ~14x14mm) * - 2x2_1206x4_horizontal (only if node is large enough, ~14x14mm) */ declare class HyperJumperPrepatternSolver2 extends HyperParameterSupervisorSolver { constructorParams: HyperJumperPrepatternSolver2Params; nodeWithPortPoints: NodeWithPortPoints; colorMap: Record; traceWidth: number; obstacleMargin: number; connMap?: ConnectivityMap; baseHyperParameters?: JumperPrepatternSolver2HyperParameters; availableJumperTypes: JumperType[]; solvedRoutes: HighDensityIntraNodeRouteWithJumpers[]; jumpers: Jumper$1[]; constructor(params: HyperJumperPrepatternSolver2Params); getConstructorParams(): HyperJumperPrepatternSolver2Params; getHyperParameterDefs(): { name: string; possibleValues: Array>; }[]; /** * Filter out invalid row/col combinations for each jumper type. * For 0603: only allow 1, 2, 4, 6, 8 for both rows and cols * For 1206x4: allow existing values (1, 2, 3, 4, 6, 8, 10 for cols; 1, 2, 3, 4, 8 for rows) */ isValidCombination(hyperParameters: VariantHyperParameters): boolean; getCombinationDefs(): string[][]; private calculateMax0603ConfigWithTraceChannels; /** * Override initializeSolvers to use getCombinationDefs for both 0603 and 1206x4. * For 0603: uses pre-calculated max rows/cols for each orientation, trace channel count, * and pattern (grid/staggered). * For 1206x4: uses full combination of cols, rows, and orientation. */ initializeSolvers(): void; generateSolver(hyperParameters: VariantHyperParameters): JumperPrepatternSolver2_HyperGraph; computeG(solver: JumperPrepatternSolver2_HyperGraph): number; computeH(solver: JumperPrepatternSolver2_HyperGraph): number; onSolve(solver: SupervisedSolver): void; getOutput(): HighDensityIntraNodeRouteWithJumpers[]; getOutputJumpers(): Jumper$1[]; visualize(): GraphicsObject; } interface NodeAnalysis { node: NodeWithPortPoints; hasCrossings: boolean; numSameLayerCrossings: number; } /** * HighDensitySolver intelligently selects the appropriate solver for each node: * - CurvyIntraNodeSolver for nodes without crossings (uses curvy trace solver) * - IntraNodeSolverWithJumpers for single-layer nodes with crossings (uses 0603 jumpers) * * This solver processes nodes one at a time, passing adjacent obstacles from * already-solved routes to maximize trace spacing. */ declare class JumperHighDensitySolver extends BaseSolver { getSolverName(): string; allNodes: NodeWithPortPoints[]; nodeAnalyses: NodeAnalysis[]; routes: HighDensityIntraNodeRoute$1[]; colorMap: Record; traceWidth: number; obstacleMargin: number; viaDiameter: number; connMap?: ConnectivityMap; hyperParameters?: Partial; availableJumperTypes: JumperType[]; capacityMeshNodes: CapacityMeshNode[]; capacityMeshEdges: CapacityMeshEdge[]; capacityMeshNodeMap: Map; nodeAdjacencyMap: Map>; nodesWithoutCrossings: NodeWithPortPoints[]; nodesWithCrossings: NodeWithPortPoints[]; curvyIntraNodeSolvers: CurvyIntraNodeSolver[]; currentCurvySolverIndex: number; jumperSolvers: HyperJumperPrepatternSolver2[]; currentJumperSolverIndex: number; phase: "analyzing" | "curvy" | "jumpers" | "done"; jumpers: Jumper$1[]; constructor({ nodePortPoints, colorMap, traceWidth, obstacleMargin, viaDiameter, connMap, hyperParameters, capacityMeshNodes, capacityMeshEdges, availableJumperTypes, }: { nodePortPoints: NodeWithPortPoints[]; colorMap?: Record; traceWidth?: number; obstacleMargin?: number; viaDiameter?: number; connMap?: ConnectivityMap; hyperParameters?: Partial; capacityMeshNodes?: CapacityMeshNode[]; capacityMeshEdges?: CapacityMeshEdge[]; /** Available jumper types. Defaults to ["0603"] */ availableJumperTypes?: JumperType[]; }); /** * Build adjacency map from edges for quick lookup of adjacent nodes */ _buildNodeAdjacencyMap(): Map>; /** * Analyze all nodes to determine which solver to use for each */ _analyzeNodes(): void; _step(): void; /** * Compute obstacles from adjacent nodes. * Uses the edge solver's adjacency information and only considers nodes * that contain obstacles or targets. * * Rules: * - Only adjacent nodes (from edges) are considered * - Only nodes with _containsObstacle or _containsTarget are obstacles * - If node contains obstacle but no target: no networkId * - If node contains target: networkId = _targetConnectionName (or from port points) */ _getAdjacentObstacles(node: NodeWithPortPoints): AdjacentObstacle[]; /** * Initialize CurvyIntraNodeSolver for each node without crossings. * Each solver is created with adjacent obstacles from already-solved routes. */ _initializeCurvySolvers(): void; /** * Step through curvy solvers one at a time. * After each solver completes, its routes become obstacles for subsequent nodes. */ _stepCurvySolvers(): void; _initializeJumperSolvers(): void; _stepJumperSolvers(): void; computeProgress(): number; getConstructorParams(): { nodePortPoints: NodeWithPortPoints[]; colorMap: Record; traceWidth: number; obstacleMargin: number; viaDiameter: number; connMap: ConnectivityMap | undefined; hyperParameters: Partial | undefined; capacityMeshNodes: CapacityMeshNode[]; capacityMeshEdges: CapacityMeshEdge[]; availableJumperTypes: JumperType[]; }; /** * Returns ALL jumpers collected from the jumper solvers. * These include all jumpers placed in the grid (from baseGraph.jumperLocations), * not just the ones used by routes. The pads have connectedTo set based on * which routes use each jumper. */ getOutputJumpers(): Jumper$1[]; visualize(): GraphicsObject; } interface OffboardPortPoint { portPointId: string; x: number; y: number; /** The obstacle this port point is at the center of */ obstacleIndex: number; /** The offBoardConnectsTo ids this port point is associated with */ offBoardConnectionIds: OffBoardConnectionId[]; /** Available Z layers for this port point based on obstacle layers */ availableZ: number[]; } interface OffboardPathFragment { pathFragmentId: string; /** The shared offBoardConnectsTo id that connects these port points */ offBoardConnectionId: OffBoardConnectionId; /** The two port points connected by this path fragment */ portPointIds: [string, string]; /** Endpoints of this edge */ start: { x: number; y: number; }; end: { x: number; y: number; }; } type Phase = "finding_obstacles" | "creating_fragments" | "done"; interface PendingFragment { offBoardId: OffBoardConnectionId; pp1: OffboardPortPoint; pp2: OffboardPortPoint; } /** * PortPointOffboardPathFragmentSolver finds obstacles with offBoardConnectsTo * defined and creates port points at their centers. It then creates path * fragments (edges) connecting port points that share the same offBoardConnectsTo * ids. * * This enables routing through off-board connections like flex cables or * external connectors. * * The solver iterates step-by-step: * 1. Phase "finding_obstacles": Process one obstacle per step, creating port points * 2. Phase "creating_fragments": Create one path fragment per step * 3. Phase "done": Solver complete */ declare class PortPointOffboardPathFragmentSolver extends BaseSolver { getSolverName(): string; srj: SimpleRouteJson; colorMap: Record; /** Current phase of the solver */ phase: Phase; /** Index of the current obstacle being processed */ currentObstacleIndex: number; /** Obstacles that have offBoardConnectsTo defined */ offboardObstacles: Array<{ obstacle: Obstacle; index: number; }>; /** Port points created at obstacle centers */ portPoints: OffboardPortPoint[]; /** Map from portPointId to OffboardPortPoint */ portPointMap: Map; /** Path fragments connecting port points with shared offBoardConnectsTo */ pathFragments: OffboardPathFragment[]; /** Map from offBoardConnectionId to port points that share it */ offBoardConnectionToPortPoints: Map; /** Pending path fragments to create (computed after obstacle phase) */ pendingFragments: PendingFragment[]; /** Index of current fragment being created */ currentFragmentIndex: number; /** Last processed obstacle (for visualization) */ lastProcessedObstacle: { obstacle: Obstacle; index: number; } | null; /** Last created port point (for visualization) */ lastCreatedPortPoint: OffboardPortPoint | null; /** Last created path fragment (for visualization) */ lastCreatedFragment: OffboardPathFragment | null; /** Color map for offBoardConnectionIds */ offBoardColorMap: Record; constructor({ srj, colorMap, }: { srj: SimpleRouteJson; colorMap?: Record; }); _step(): void; private stepFindingObstacles; private computePendingFragments; private stepCreatingFragments; private layerToZ; computeProgress(): number; visualize(): GraphicsObject; } type BucketCoordinate = `${number}x${number}`; declare class CapacityNodeTree { nodes: CapacityMeshNode[]; buckets: Map; CELL_SIZE: number; constructor(nodes: CapacityMeshNode[]); getBucketKey(x: number, y: number): BucketCoordinate; getNodesInArea(centerX: number, centerY: number, width: number, height: number): CapacityMeshNode[]; } /** * This solver looks at every obstacle with off board connections (one per step), * then sets _offBoardConnectedCapacityMeshNodeIds on each capacity node that is * mutually connected via off board connections */ declare class RelateNodesToOffBoardConnectionsSolver extends BaseSolver { input: { capacityMeshNodes: CapacityMeshNode[]; srj: SimpleRouteJson; }; getSolverName(): string; unprocessedObstacles: Obstacle[]; nodeTree: CapacityNodeTree; offBoardConnMap: ConnectivityMap$1; nodesInNet: Map; lastProcessedObstacle?: Obstacle; constructor(input: { capacityMeshNodes: CapacityMeshNode[]; srj: SimpleRouteJson; }); _step(): void; getOutput(): { capacityNodes: CapacityMeshNode[]; }; visualize(): GraphicsObject; } interface MovablePoint { x: number; y: number; z: number; rootConnectionName?: string; connectionName: string; forceX?: number; forceY?: number; } interface RouteInProgress { connectionName: string; rootConnectionName?: string; startPoint: { x: number; y: number; z: number; }; endPoint: { x: number; y: number; z: number; }; movablePoints: MovablePoint[]; } /** * A simplified high density solver that directly connects port points * within each node without considering intersections or vias. * * This solver creates 3-segment lines (4 points) for each connection and uses * a force-directed approach to push movable points away from borders and * other movable points with different rootConnectionName. * * Only solves intra-node routing - connecting port points within a single node. */ declare class SimpleHighDensitySolver extends BaseSolver { getSolverName(): string; unsolvedNodes: NodeWithPortPoints[]; allNodes: NodeWithPortPoints[]; routes: HighDensityIntraNodeRoute$1[]; colorMap: Record; traceWidth: number; viaDiameter: number; numMovablePoints: number; currentNode: NodeWithPortPoints | null; lastNode: NodeWithPortPoints | null; currentNodeStep: number; routesInProgress: RouteInProgress[]; pushMargin: number; currentNodeBounds: { minX: number; maxX: number; minY: number; maxY: number; } | null; constructor({ nodePortPoints, colorMap, traceWidth, viaDiameter, pushMargin, numMovablePoints, }: { nodePortPoints: NodeWithPortPoints[]; colorMap?: Record; traceWidth?: number; viaDiameter?: number; numMovablePoints?: number; pushMargin?: number; }); _step(): void; _initializeRoutesForCurrentNode(): void; _runForceDirectedStep(): void; _finalizeRoutesForCurrentNode(): void; _getNodeBounds(node: NodeWithPortPoints): { minX: number; maxX: number; minY: number; maxY: number; }; visualize(): GraphicsObject; } interface CapacityMeshSolverOptions$7 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; } type PipelineStep$7 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AssignableAutoroutingPipeline2) => ConstructorParameters; onSolved?: (instance: AssignableAutoroutingPipeline2) => void; }; declare class AssignableAutoroutingPipeline2 extends BaseSolver { readonly srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$7; getSolverName(): string; netToPointPairsSolver?: NetToPointPairsSolver; nodeSolver?: RectDiffPipeline; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; relateNodesToOffBoardConnections?: RelateNodesToOffBoardConnectionsSolver; colorMap: Record; highDensityRouteSolver?: HighDensitySolver; /** @deprecated Use highDensitySolver instead */ simpleHighDensityRouteSolver?: SimpleHighDensitySolver; highDensitySolver?: JumperHighDensitySolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; offboardPathFragmentSolver?: PortPointOffboardPathFragmentSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; traceKeepoutSolver?: TraceKeepoutSolver; traceWidthSolver?: TraceWidthSolver; availableSegmentPointSolver?: AvailableSegmentPointSolver; portPointPathingSolver?: PortPointPathingSolver; multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer; viaDiameter: number; minTraceWidth: number; effort: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithPointPairs?: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7 | PipelineStep$7)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$7); getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$7]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; /** * A lightweight version of the visualize method that can be used to stream * progress * * We return the most relevant graphic for the stage: * 1. netToPointPairs output * 2. Capacity Planning Output * 3. High Density Route Solver Output, max 200 lines */ preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; getConnectedOffboardObstacles(): Record; /** * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces */ getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } type UnsolvedRouteWithOrder = { connectionName: string; hdRoutes: HighDensityIntraNodeRoute$1[]; /** Node IDs in order from start to end */ nodeOrder: string[]; start: { x: number; y: number; z: number; }; end: { x: number; y: number; z: number; }; }; /** * MultipleHighDensityRouteStitchSolver2 uses path ordering information from * the port point pathing solver to correctly stitch routes that may reuse * the same node multiple times. * * Unlike the original solver that uses connectivity maps to find endpoints, * this version uses the node traversal order from the pathing solver. */ declare class MultipleHighDensityRouteStitchSolver2 extends BaseSolver { getSolverName(): string; unsolvedRoutes: UnsolvedRouteWithOrder[]; mergedHdRoutes: HighDensityIntraNodeRoute$1[]; colorMap: Record; defaultTraceThickness: number; defaultViaDiameter: number; constructor(params: { connections: SimpleRouteConnection[]; hdRoutes: HighDensityIntraNodeRoute$1[]; /** Connection path results from port point pathing solver */ connectionPathResults: ConnectionPathResult[]; colorMap?: Record; layerCount: number; defaultViaDiameter?: number; }); _step(): void; /** * Stitch routes together using the node order from pathing results. * * The key insight is that each HD route corresponds to a segment within a * capacity node. The nodeOrder tells us which nodes we visit in sequence. * We use this to order the routes correctly, even when a node is visited * multiple times. */ private stitchOrderedRoutes; /** * Order routes based on the node traversal path. * Each node in nodeOrder may have one or more routes. * Returns routes in the order they should be stitched. * * Uses a two-phase approach: * 1. Find the route closest to start, build chain forward * 2. From the connection point of first route, build chain backward * to catch any routes that come before */ private orderRoutesByNodePath; /** * Fallback: order routes by proximity, starting from the start point. */ private orderRoutesByProximity; visualize(): GraphicsObject; } interface CapacityMeshSolverOptions$6 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; } type PipelineStep$6 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AssignableAutoroutingPipeline3) => ConstructorParameters; onSolved?: (instance: AssignableAutoroutingPipeline3) => void; }; declare class AssignableAutoroutingPipeline3 extends BaseSolver { readonly srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$6; getSolverName(): string; netToPointPairsSolver?: NetToPointPairsSolver; traceKeepoutSolver?: TraceKeepoutSolver; nodeSolver?: RectDiffPipeline; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; relateNodesToOffBoardConnections?: RelateNodesToOffBoardConnectionsSolver; colorMap: Record; highDensityRouteSolver?: HighDensitySolver; /** @deprecated Use highDensitySolver instead */ simpleHighDensityRouteSolver?: SimpleHighDensitySolver; highDensitySolver?: JumperHighDensitySolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver2; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; offboardPathFragmentSolver?: PortPointOffboardPathFragmentSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; traceWidthSolver?: TraceWidthSolver; availableSegmentPointSolver?: AvailableSegmentPointSolver; portPointPathingSolver?: PortPointPathingSolver; multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer; viaDiameter: number; minTraceWidth: number; effort: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithPointPairs?: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$6 | PipelineStep$6 | PipelineStep$6 | PipelineStep$6 | PipelineStep$6 | PipelineStep$6 | PipelineStep$6 | PipelineStep$6 | PipelineStep$6)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$6); getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$6]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; /** * A lightweight version of the visualize method that can be used to stream * progress * * We return the most relevant graphic for the stage: * 1. netToPointPairs output * 2. Capacity Planning Output * 3. High Density Route Solver Output, max 200 lines */ preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; getConnectedOffboardObstacles(): Record; /** * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces */ getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; /** * Collects ALL jumpers from the highDensitySolver and converts them to SRJ Jumper format. * This returns all jumpers placed in the jumper grid (from baseGraph.jumperLocations), * not just the ones used by routes. These will be used as obstacles for the keepout * solver and added to the final SRJ output. */ getOutputJumpers(): Jumper$1[]; getOutputSimpleRouteJson(): SimpleRouteJson; } type ExploredPortPoint = { port: SegmentPortPoint; depth: number; parent: ExploredPortPoint | null; countOfCrampedPortPointsInPath: number; }; type SingleTargetNecessaryCrampedPortPointSolverInput = { target: CapacityMeshNode; mapOfCapacityMeshNodeIdToSegmentPortPoints: Map; mapOfCapacityMeshNodeIdToRef: Map; depthLimit: number; shouldIgnoreCrampedPortPoints: boolean; }; declare class SingleTargetNecessaryCrampedPortPointSolver extends BaseSolver$1 { private input; private queue; private resultExploredPortPoints; private currentExploredPortPoints; private visitedExploredPortPoints; constructor(input: SingleTargetNecessaryCrampedPortPointSolverInput); getSolverName(): string; _setup(): void; _step(): void; private getCandidateCost; getOutput(): ExploredPortPoint[]; visualize(): GraphicsObject; } type MultiTargetNecessaryCrampedPortPointSolverInput = { sharedEdgeSegments: SharedEdgeSegment[]; capacityMeshNodes: CapacityMeshNode[]; simpleRouteJson: SimpleRouteJson; /** * The number of cramped port points to keep. * This is useful when there are multiple connections. * Setting this to more than one (e.g., 2) ensures that at least two connections can be routed. * Higher values may be beneficial, but can lead to more DRC errors. */ numberOfCrampedPortPointsToKeep: number; }; /** * This solver filters out cramped port points that are not necessary. */ declare class MultiTargetNecessaryCrampedPortPointSolver extends BaseSolver$1 { private input; private unprocessedTargets; private targetNode; private currentTarget; private crampedPortPointsToKeep; private candidatesAtDepth; private isRunningCrampedPass; private filteredOutput?; activeSubSolver: SingleTargetNecessaryCrampedPortPointSolver | null; /** * NOTE: I do not like maps, add a capacityMeshNode ref inside SegmentPortPoints * in future so we do not need the capacityMeshNodeId */ private nodeMap; private mapOfCapacityMeshNodeIdToSegmentPortPoints; constructor(input: MultiTargetNecessaryCrampedPortPointSolverInput); getSolverName(): string; _setup(): void; _step(): void; getOutput(): SharedEdgeSegment[]; private isMultilayerEscapePort; visualize(): GraphicsObject; } type RawPort = { portId: string; x: number; y: number; z: number; distToCentermostPortOnZ: number; cramped?: boolean; regions: RegionHg[]; tinyHypergraphPortPenalty?: number; }; type RegionPortHg = Omit & { d: RawPort; }; type RegionHg = Omit & { d: CapacityMeshNode; assignments?: RegionPortAssignmentHg[]; ports: RegionPortHg[]; }; type HyperGraphHg = Omit & { ports: RegionPortHg[]; regions: RegionHg[]; }; type ConnectionHg = Omit & { startRegion: RegionHg; endRegion: RegionHg; simpleRouteConnection?: SimpleRouteConnection; }; type CandidateHg = Omit & { port: RegionPortHg; parent?: CandidateHg; lastPort?: RegionPortHg; lastRegion?: RegionHg; nextRegion?: RegionHg; ripRequired: boolean; }; type SolvedRoutesHg = Omit & { path: CandidateHg[]; connection: ConnectionHg; }; type RegionPortAssignmentHg = Omit & { regionPort1: RegionPortHg; regionPort2: RegionPortHg; region: RegionHg; connection: ConnectionHg; solvedRoute: SolvedRoutesHg; }; type RegionId = CapacityMeshNodeId; type RegionMemoryPfMap = Map; interface HgPortPointPathingSolverParams { graph: HyperGraphHg; connections: ConnectionHg[]; colorMap?: Record; inputSolvedRoutes?: SolvedRoutesHg[]; layerCount: number; effort: number; minViaPadDiameter?: number; flags: { FORCE_CENTER_FIRST: boolean; RIPPING_ENABLED: boolean; }; weights: { /** Seed used for deterministic shuffling in rip-selection ordering. */ SHUFFLE_SEED: number; /** Multiplier for center-offset penalty in heuristic h (larger = prefer centermost ports). */ CENTER_OFFSET_DIST_PENALTY_FACTOR: number; /** Center-offset amount ignored before penalty starts in heuristic h. */ CENTER_OFFSET_FOCUS_SHIFT: number; /** A* greediness factor: f = g + GREEDY_MULTIPLIER * h. */ GREEDY_MULTIPLIER: number; /** Scales exact Pf-delta step cost in g (higher = stronger congestion avoidance). */ NODE_PF_FACTOR: number; /** Flat added cost when transition changes layer (z differs). */ LAYER_CHANGE_COST: number; /** Cost associated with ripping a region due to Pf threshold. */ RIPPING_PF_COST: number; /** Maximum cap applied to Pf-derived costs to avoid explosive scores. */ NODE_PF_MAX_PENALTY: number; /** Scales memory-Pf contribution in heuristic h (bias away from historically bad regions). */ MEMORY_PF_FACTOR: number; /** Base geometric transition multiplier used by auxiliary step penalties. */ BASE_CANDIDATE_COST: number; /** Soft board-score guard for candidate filtering; more negative allows riskier paths. */ MIN_ALLOWED_BOARD_SCORE: number; /** Per-connection candidate queue cap (0 means use default queue size). */ MAX_ITERATIONS_PER_PATH: number; /** Distance threshold where heuristic is suppressed to encourage initial exploration. */ RANDOM_WALK_DISTANCE: number; /** Initial region Pf threshold for ripping decisions. */ START_RIPPING_PF_THRESHOLD: number; /** Final region Pf threshold as region rip-count approaches its cap. */ END_RIPPING_PF_THRESHOLD: number; /** Global limit for total rip operations in one solve run. */ MAX_RIPS: number; /** Fraction of extra random rips added when ripping is triggered. */ RANDOM_RIP_FRACTION: number; /** Multiplier for straight-line deviation penalty in heuristic h. */ STRAIGHT_LINE_DEVIATION_PENALTY_FACTOR: number; }; opts?: { regionMemoryPfMap?: RegionMemoryPfMap; }; } /** Solves port-point routing over an HG hypergraph using heuristics and optional ripping. */ declare class HgPortPointPathingSolver extends HyperGraphSolver { private params; private regionMemoryPfMap; private baseRegionFailureCostMap; private regionRipCountMap; private totalRipCount; constructor(params: HgPortPointPathingSolverParams); estimateCostToEnd(port: RegionPortHg): number; computeH(candidate: CandidateHg): number; computeIncreasedRegionCostIfPortsAreUsed(region: RegionHg, port1: RegionPortHg, port2: RegionPortHg): number; computeG(candidate: CandidateHg): number; getPortUsagePenalty(port: RegionPortHg): number; getRipsRequiredForPortUsage(region: RegionHg, port1: RegionPortHg, port2: RegionPortHg): RegionPortAssignment[]; selectCandidatesForEnteringRegion(candidates: CandidateHg[]): CandidateHg[]; routeSolvedHook(solvedRoute: SolvedRoutesHg): void; computeRoutesToRip(newlySolvedRoute: SolvedRoutesHg): Set; private computeDeviation; private computeDistanceTraveled; private computeMemoryPfPenalty; private computeEndRegionCloseCost; private getCenterFirstEnteringRegionCandidates; private isPortAvailableForCurrentNet; private computeRegionPfFromAssignments; private clampPf; private get NODE_MAX_PF(); private pfToFailureCost; private getBaseRegionFailureCost; private getRegionAssignedPortPoints; private computeRegionPfWithAdditionalSegment; private getRegionRippingPfThreshold; private computeRegionPf; computeNodePf(node: InputNodeWithPortPoints): number | null; getOutput(): { nodesWithPortPoints: NodeWithPortPoints$1[]; inputNodeWithPortPoints: InputNodeWithPortPoints[]; }; visualize(): GraphicsObject; private visualizePfOverlay; } interface CapacityMeshSolverOptions$5 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; } type PipelineStep$5 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AutoroutingPipelineSolver3_HgPortPointPathing) => ConstructorParameters; onSolved?: (instance: AutoroutingPipelineSolver3_HgPortPointPathing) => void; }; declare class AutoroutingPipelineSolver3_HgPortPointPathing extends BaseSolver { readonly srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$5; netToPointPairsSolver?: NetToPointPairsSolver; nodeSolver?: RectDiffPipeline; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; colorMap: Record; highDensityRouteSolver?: HighDensitySolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; availableSegmentPointSolver?: AvailableSegmentPointSolver; portPointPathingSolver?: HgPortPointPathingSolver; multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer; uniformPortDistributionSolver?: UniformPortDistributionSolver; traceWidthSolver?: TraceWidthSolver; necessaryCrampedPortPointSolver?: MultiTargetNecessaryCrampedPortPointSolver; hyperGraphSectionOptimizer?: HyperGraphSectionOptimizer; viaDiameter: number; minTraceWidth: number; effort: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithPointPairs?: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5 | PipelineStep$5)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$5); getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$5]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } declare class NodeDimensionSubdivisionSolver extends BaseSolver { private readonly nodes; private readonly maxNodeDimension; private readonly maxNodeRatio; private readonly minNodeArea; readonly outputNodes: CapacityMeshNode[]; constructor(nodes: CapacityMeshNode[], maxNodeDimension: number, maxNodeRatio?: number, minNodeArea?: number); getSolverName(): string; private getSubdivisionGrid; private shouldRemoveNode; private subdivideNode; _step(): void; visualize(): GraphicsObject; } declare class TinyHypergraphPortPointPathingSolver extends BaseSolver { private params; private tinyPipelineSolver; private duplicateCongestedPortReport?; private duplicateCongestedPortError?; private duplicatedPortCount; private inputNodeWithPortPoints; private originalRegionById; private originalRegionIds; constructor(params: HgPortPointPathingSolverParams); getSolverName(): string; _step(): void; preview(): GraphicsObject; private getCurrentTinySolver; private getSolvedTinySolver; private getRouteMetadata; private createAssignedPortPoint; getOutput(): { nodesWithPortPoints: NodeWithPortPoints[]; inputNodeWithPortPoints: InputNodeWithPortPoints[]; }; computeNodePf(node: InputNodeWithPortPoints): number | null; tryFinalAcceptance(): void; getConstructorParams(): readonly [HgPortPointPathingSolverParams]; visualize(): GraphicsObject; } interface EscapeViaMetadata { pointId: string; x: number; y: number; connectionName: string; rootConnectionName: string; sourcePointIndex: number; sourcePointId?: string; sourceLayer: string; targetLayer: string; targetPourKey: string; } interface EscapeViaLocationSolverOptions { viaDiameter?: number; minTraceWidth?: number; obstacleMargin?: number; } declare class EscapeViaLocationSolver extends BaseSolver { readonly ogSrj: SimpleRouteJson; getSolverName(): string; viaDiameter: number; viaRadius: number; minTraceWidth: number; obstacleMargin: number; escapeOffset: number; requiredTraceClearance: number; requiredViaToViaClearance: number; outputSrj: SimpleRouteJson; escapeViaMetadataByPointId: Map; createdEscapeVias: EscapeViaMetadata[]; nextEscapeViaIndex: number; constructor(ogSrj: SimpleRouteJson, opts?: EscapeViaLocationSolverOptions); private getConnectionNetIds; private obstacleMatchesConnectionNet; private getObstacleZs; private getViaSpanLayers; private createEscapeViaObstacle; private selectSourceObstacle; private getCandidatePositions; private dedupeCandidatePositions; private pushEdgeSample; private getEdgeSamples; private isInsideBoard; private hasClearEscapePath; private getBoardBoundarySegments; private getRayProbeDistance; private getRayIntersectionDistance; private getProjectedFreeSpace; private getProjectedFreeSpaceAlongDirection; private getMinBlockingClearance; private getMinPlacedEscapeViaClearance; private selectPointOwner; private findBestEscapeViaCandidate; private buildPointPlacementPlans; _step(): void; getOutputSimpleRouteJson(): SimpleRouteJson; getEscapeViaMetadataByPointId(): Map; visualize(): GraphicsObject; } type RepairSampleEntry = { node: NodeWithPortPoints; routeIndexes: number[]; sample: DatasetSample; }; declare class Pipeline4HighDensityRepairSolver extends BaseSolver { readonly repairMargin: number; readonly sampleEntries: RepairSampleEntry[]; readonly originalHdRoutes: HighDensityRoute$1[]; readonly originalNodeWithPortPoints: NodeWithPortPoints[]; readonly originalObstacles: Obstacle[]; readonly obstacleSHI: ObstacleSpatialHashIndex; readonly colorMap: Record; repairedRoutesByIndex: Map; activeSampleIndex: number; activeSubSolver: HighDensityRepairSolver | null; latestVisualization: GraphicsObject; constructor(params: { nodeWithPortPoints: NodeWithPortPoints[]; hdRoutes: HighDensityRoute$1[]; obstacles: Obstacle[]; repairMargin?: number; colorMap?: Record; maxSampleEntries?: number; }); getSolverName(): string; getConstructorParams(): readonly [{ readonly nodeWithPortPoints: NodeWithPortPoints[]; readonly hdRoutes: HighDensityIntraNodeRoute$1[]; readonly obstacles: Obstacle[]; readonly repairMargin: number; readonly colorMap: Record; }]; _step(): void; getOutput(): HighDensityRoute$1[]; visualize(): GraphicsObject; } declare class SingleHighDensityRouteStitchSolver3 extends BaseSolver { getSolverName(): string; mergedHdRoute: HighDensityIntraNodeRoute$1; remainingHdRoutes: HighDensityIntraNodeRoute$1[]; start: Point3; end: Point3; colorMap: Record; allowedLayerTransitionPointKeys?: Set; constructor(opts: { connectionName: string; hdRoutes: HighDensityIntraNodeRoute$1[]; start: Point3; end: Point3; colorMap?: Record; defaultTraceThickness?: number; defaultViaDiameter?: number; allowedLayerTransitionPointKeys?: Set; }); getDisjointedRoute(): { firstRoute: HighDensityIntraNodeRoute$1; }; _step(): void; visualize(): GraphicsObject; } type UnsolvedRoute3 = { connectionName: string; hdRoutes: HighDensityIntraNodeRoute$1[]; start: Point3; end: Point3; }; declare class MultipleHighDensityRouteStitchSolver3 extends BaseSolver { getSolverName(): string; unsolvedRoutes: UnsolvedRoute3[]; activeSolver: SingleHighDensityRouteStitchSolver3 | null; mergedHdRoutes: HighDensityIntraNodeRoute$1[]; colorMap: Record; defaultTraceThickness: number; defaultViaDiameter: number; allowedLayerTransitionPointKeys?: Set; private endpointIndex; private canStitchBetweenTerminals; private getSharedRootPathRoutes; constructor(params: { connections: SimpleRouteConnection[]; hdRoutes: HighDensityIntraNodeRoute$1[]; colorMap?: Record; layerCount: number; defaultViaDiameter?: number; allowedLayerTransitionPointKeys?: Set; }); _step(): void; visualize(): GraphicsObject; } declare class PreprocessSimpleRouteJsonSolver$1 extends BaseSolver { readonly inputSrj: SimpleRouteJson; outputSrj?: SimpleRouteJson; constructor(inputSrj: SimpleRouteJson); _step(): void; getOutputSimpleRouteJson(): SimpleRouteJson; getConstructorParams(): readonly [SimpleRouteJson]; visualize(): GraphicsObject; } interface CapacityMeshSolverOptions$4 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; maxNodeDimension?: number; maxNodeRatio?: number; minNodeArea?: number; } type AutoroutingPipelineSolverOptions$1 = CapacityMeshSolverOptions$4; type PipelineStep$4 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AutoroutingPipelineSolver4_TinyHypergraph) => ConstructorParameters; onSolved?: (instance: AutoroutingPipelineSolver4_TinyHypergraph) => void; }; declare class AutoroutingPipelineSolver4_TinyHypergraph extends BaseSolver { srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$4; preprocessSimpleRouteJsonSolver?: PreprocessSimpleRouteJsonSolver$1; escapeViaLocationSolver?: EscapeViaLocationSolver; netToPointPairsSolver?: NetToPointPairsSolver; nodeSolver?: RectDiffPipeline; nodeDimensionSubdivisionSolver?: NodeDimensionSubdivisionSolver; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; colorMap: Record; highDensityRouteSolver?: HighDensitySolver; highDensityForceImproveSolver?: HighDensityForceImproveSolver; highDensityRepairSolver?: Pipeline4HighDensityRepairSolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver3; globalDrcForceImproveSolver?: GlobalDrcForceImproveSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; availableSegmentPointSolver?: AvailableSegmentPointSolver; portPointPathingSolver?: TinyHypergraphPortPointPathingSolver; multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer; uniformPortDistributionSolver?: UniformPortDistributionSolver; traceWidthSolver?: TraceWidthSolver; necessaryCrampedPortPointSolver?: MultiTargetNecessaryCrampedPortPointSolver; viaDiameter: number; viaHoleDiameter: number; minTraceWidth: number; effort: number; maxNodeDimension: number; maxNodeRatio: number; minNodeArea: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithEscapeViaLocations?: SimpleRouteJson; srjWithPointPairs?: SimpleRouteJson; originalSrj: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; highDensityNodePortPoints?: NodeWithPortPoints[]; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4 | PipelineStep$4)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$4); private setSimpleRouteJson; getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$4]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } type AutoroutingPipelineSolver5Options = AutoroutingPipelineSolverOptions$1 & { hdCacheBaseUrl?: string; hdCacheFetch?: typeof fetch; }; declare class AutoroutingPipelineSolver5_HdCache extends AutoroutingPipelineSolver4_TinyHypergraph { readonly hdCacheBaseUrl: string; readonly hdCacheFetch?: typeof fetch; constructor(srj: ConstructorParameters[0], opts?: AutoroutingPipelineSolver5Options); private replaceHighDensityPipelineStep; stepAsync(): Promise; solveAsync(): Promise; solve(): void; } type Point$1 = { x: number; y: number; }; type Matrix3x3 = [ number, number, number, number, number, number, number, number, number ]; type ProjectedRect = { center: Point$1; width: number; height: number; innerWidth: number; innerHeight: number; ccwRotationDegrees: number; ccwRotationRadians: number; polygonArea: number; equivalentAreaExpansionFactor: number; targetQuad: [Point$1, Point$1, Point$1, Point$1]; rectToPolygonMatrix: Matrix3x3; polygonToRectMatrix: Matrix3x3; }; type PolyPortPoint = PortPoint & { originalPoint?: Point$1; projectedPoint?: Point$1; }; type PolyNodeWithPortPoints = Omit & { polygon: Point$1[]; portPoints: PolyPortPoint[]; projectedRect?: ProjectedRect; }; declare class AttachProjectedRectsSolver extends BaseSolver { params: { nodesWithPortPoints: PolyNodeWithPortPoints[]; equivalentAreaExpansionFactor?: number; minProjectedRectDimension?: number; traceWidth?: number; viaDiameter?: number; obstacleMargin?: number; }; getSolverName(): string; outputNodes: PolyNodeWithPortPoints[]; projectionAdjustmentByNodeId: Map; constructor(params: { nodesWithPortPoints: PolyNodeWithPortPoints[]; equivalentAreaExpansionFactor?: number; minProjectedRectDimension?: number; traceWidth?: number; viaDiameter?: number; obstacleMargin?: number; }); _step(): void; getOutput(): PolyNodeWithPortPoints[]; getConstructorParams(): readonly [{ nodesWithPortPoints: PolyNodeWithPortPoints[]; equivalentAreaExpansionFactor?: number; minProjectedRectDimension?: number; traceWidth?: number; viaDiameter?: number; obstacleMargin?: number; }]; visualize(): GraphicsObject; } type ProjectedPortRecord = { projected: PortPoint; original: PortPoint; }; declare class PolySingleIntraNodeSolver extends BaseSolver { params: { nodeWithPortPoints: PolyNodeWithPortPoints; colorMap?: Record; connMap?: ConnectivityMap; viaDiameter?: number; traceWidth?: number; obstacleMargin?: number; effort?: number; }; getSolverName(): string; highDensitySolver: HyperSingleIntraNodeSolver; projectedNode: NodeWithPortPoints; solvedRoutes: HighDensityIntraNodeRoute$1[]; projectedPorts: ProjectedPortRecord[]; constructor(params: { nodeWithPortPoints: PolyNodeWithPortPoints; colorMap?: Record; connMap?: ConnectivityMap; viaDiameter?: number; traceWidth?: number; obstacleMargin?: number; effort?: number; }); _step(): void; getConstructorParams(): readonly [{ nodeWithPortPoints: PolyNodeWithPortPoints; colorMap?: Record; connMap?: ConnectivityMap; viaDiameter?: number; traceWidth?: number; obstacleMargin?: number; effort?: number; }]; visualize(): GraphicsObject; } declare class PolyHighDensitySolver extends BaseSolver { getSolverName(): string; unsolvedNodePortPoints: PolyNodeWithPortPoints[]; nodePortPoints: PolyNodeWithPortPoints[]; routes: HighDensityIntraNodeRoute$1[]; routesByNodeId: Map; failedSolvers: PolySingleIntraNodeSolver[]; activeSubSolver: PolySingleIntraNodeSolver | null; colorMap: Record; connMap?: ConnectivityMap; viaDiameter: number; traceWidth: number; obstacleMargin: number; effort: number; nodePfById: Map; constructor({ nodePortPoints, colorMap, connMap, viaDiameter, traceWidth, obstacleMargin, effort, nodePfById, }: { nodePortPoints: PolyNodeWithPortPoints[]; colorMap?: Record; connMap?: ConnectivityMap; viaDiameter?: number; traceWidth?: number; obstacleMargin?: number; effort?: number; nodePfById?: Map | Record; }); _step(): void; computeProgress(): number; getConstructorParams(): readonly [{ readonly nodePortPoints: PolyNodeWithPortPoints[]; readonly colorMap: Record; readonly connMap: ConnectivityMap | undefined; readonly viaDiameter: number; readonly traceWidth: number; readonly obstacleMargin: number; readonly effort: number; readonly nodePfById: Map; }]; visualize(): GraphicsObject; } type PolyHypergraphPortPointPathingSolverOptions = { srj: SimpleRouteJson; effort?: number; concavityTolerance?: number; layerMergeMode?: LayerMergeMode; portSpacing?: number; portMarginFromSegmentEndpoint?: number; useConstrainedDelaunay?: boolean; usePolyanyaMerge?: boolean; viaSegments?: number; }; declare class PolyHypergraphPortPointPathingSolver extends BaseSolver { params: PolyHypergraphPortPointPathingSolverOptions; getSolverName(): string; convexRegions: ConvexRegionsComputeResult; serializedGraph: SerializedPolyHyperGraph; loaded: PolyHyperGraphLoadResult; polySolver: PolyHyperGraphSolver & BaseSolver; inputNodeWithPortPoints: InputNodeWithPortPoints[]; nodesWithPortPoints: PolyNodeWithPortPoints[]; reservedRegionCount: number; clearance: number; effort: number; usedUnconstrainedDelaunayFallback: boolean; constructor(params: PolyHypergraphPortPointPathingSolverOptions); private createInputNodesWithPortPoints; private createAssignedPortPoint; private buildOutputNodes; _step(): void; getOutput(): { nodesWithPortPoints: PolyNodeWithPortPoints[]; inputNodeWithPortPoints: InputNodeWithPortPoints[]; }; computeNodePf(node: InputNodeWithPortPoints): number | null; getConstructorParams(): readonly [PolyHypergraphPortPointPathingSolverOptions]; preview(): GraphicsObject; visualize(): GraphicsObject; } declare class PreprocessSimpleRouteJsonSolver extends BaseSolver { readonly inputSrj: SimpleRouteJson; outputSrj?: SimpleRouteJson; constructor(inputSrj: SimpleRouteJson); _step(): void; getOutputSimpleRouteJson(): SimpleRouteJson; getConstructorParams(): readonly [SimpleRouteJson]; visualize(): GraphicsObject; } declare class ProjectHighDensityToPolygonSolver extends BaseSolver { getSolverName(): string; routes: HighDensityIntraNodeRoute$1[]; routesByNodeId: Map; colorMap: Record; nodePortPoints: PolyNodeWithPortPoints[]; rawRoutesByNodeId: Map; constructor({ nodePortPoints, routesByNodeId, colorMap, }: { nodePortPoints: PolyNodeWithPortPoints[]; routesByNodeId: Map | Record; colorMap?: Record; }); _step(): void; getOutput(): HighDensityIntraNodeRoute$1[]; getConstructorParams(): readonly [{ readonly nodePortPoints: PolyNodeWithPortPoints[]; readonly routesByNodeId: Map; readonly colorMap: Record; }]; visualize(): GraphicsObject; } interface CapacityMeshSolverOptions$3 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; maxNodeDimension?: number; maxNodeRatio?: number; minNodeArea?: number; equivalentAreaExpansionFactor?: number; minProjectedRectDimension?: number; polyConcavityTolerance?: number; polyPortSpacing?: number; polyPortMarginFromSegmentEndpoint?: number; } type PipelineStep$3 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AutoroutingPipelineSolver6_PolyHypergraph) => ConstructorParameters; onSolved?: (instance: AutoroutingPipelineSolver6_PolyHypergraph) => void; }; declare class AutoroutingPipelineSolver6_PolyHypergraph extends BaseSolver { srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$3; preprocessSimpleRouteJsonSolver?: PreprocessSimpleRouteJsonSolver; escapeViaLocationSolver?: EscapeViaLocationSolver; netToPointPairsSolver?: NetToPointPairsSolver; polyGraphSolver?: PolyHypergraphPortPointPathingSolver; attachProjectedRectsSolver?: AttachProjectedRectsSolver; highDensityRouteSolver?: PolyHighDensitySolver; projectHighDensityToPolgonSolver?: ProjectHighDensityToPolygonSolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver3; traceSimplificationSolver?: TraceSimplificationSolver; traceWidthSolver?: TraceWidthSolver; globalDrcForceImproveSolver?: GlobalDrcForceImproveSolver; colorMap: Record; viaDiameter: number; viaHoleDiameter: number; minTraceWidth: number; effort: number; maxNodeDimension: number; maxNodeRatio: number; minNodeArea: number; equivalentAreaExpansionFactor: number; minProjectedRectDimension: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithEscapeViaLocations?: SimpleRouteJson; srjWithPointPairs?: SimpleRouteJson; originalSrj: SimpleRouteJson; highDensityNodePortPoints?: PolyNodeWithPortPoints[]; projectedHighDensityNodePortPoints?: PolyNodeWithPortPoints[]; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3 | PipelineStep$3)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$3); private setSimpleRouteJson; getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$3]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; private getProblemVisualization; visualize(): GraphicsObject; preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } type ComponentKind = "bga" | "qfp" | "qfp_thermalpad" | "soic"; /** * Current detection stage: groups SRJ obstacles by component and replaces each * component's member pads with one rectangular bounds obstacle. */ declare class RectBoundsComponentDetectionStage extends BaseSolver$1 { readonly inputSrj: SimpleRouteJson; private initialized; private groupedComponentObstacles; private groupedComponentKinds; private unprocessedComponentIds; private detectedComponents; private currentComponentId; private currentMemberObstacles; private output; constructor({ inputSrj }: ComponentDetectionSolverParams); getConstructorParams(): readonly [{ readonly inputSrj: SimpleRouteJson; }]; _step(): void; getOutput(): ComponentDetectionSolverOutput; visualize(): GraphicsObject; preview(): GraphicsObject; private initializeDetectionState; private processNextComponent; private finalizeOutput; private groupObstaclesByComponentId; private createDetectedComponent; private getVisualizationTitle; } interface ComponentDetectionSolverParams { inputSrj: SimpleRouteJson; } interface DetectedComponent { componentId: string; componentKind: ComponentKind; bounds: { __type: "rect"; } & SimpleRouteJson["bounds"]; } type ComponentDetectionSolverOutput = DetectedComponent[]; /** * Pipeline wrapper for component detection stages. The current pipeline only * runs the rectangular bounds stage, but later shape-specific stages can be * inserted here without changing the external solver API. */ declare class ComponentDetectionSolver extends BasePipelineSolver { rectBoundsComponentDetection?: RectBoundsComponentDetectionStage; pipelineDef: PipelineStep$a[]; getConstructorParams(): readonly [ComponentDetectionSolverParams]; getOutput(): ComponentDetectionSolverOutput; initialVisualize(): GraphicsObject | null; } interface ComponentTopologyGeneratorSolverParams { detectedComponents: DetectedComponent[]; inputSrj: SimpleRouteJson; } type ComponentTopologyGeneratorSolverOutput = CapacityMeshNode[]; declare class ComponentTopologyGeneratorSolver extends BaseSolver { readonly inputProblem: ComponentTopologyGeneratorSolverParams; private output; private componentMeshNodes; private currentComponentIndex; private activeTopologyGenerator; constructor(inputProblem: ComponentTopologyGeneratorSolverParams); getConstructorParams(): readonly [ComponentTopologyGeneratorSolverParams]; _step(): void; private finalizeComponentTopology; createComponentObstacleSrj(inputSrj?: SimpleRouteJson): SimpleRouteJson; visualize(): GraphicsObject; getOutput(): ComponentTopologyGeneratorSolverOutput; } interface CapacityMeshSolverOptions$2 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; maxNodeDimension?: number; maxNodeRatio?: number; minNodeArea?: number; } type PipelineStep$2 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AutoroutingPipelineSolver7_MultiGraph) => ConstructorParameters; onSolved?: (instance: AutoroutingPipelineSolver7_MultiGraph) => void; }; declare class AutoroutingPipelineSolver7_MultiGraph extends BaseSolver { srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$2; getSolverName(): string; preprocessSimpleRouteJsonSolver?: PreprocessSimpleRouteJsonSolver$1; escapeViaLocationSolver?: EscapeViaLocationSolver; netToPointPairsSolver?: NetToPointPairsSolver; componentTopologyGeneratorSolver?: ComponentTopologyGeneratorSolver; globalTopologyGeneratorSolver?: RectDiffPipeline; nodeDimensionSubdivisionSolver?: NodeDimensionSubdivisionSolver; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; colorMap: Record; highDensityRouteSolver?: HighDensitySolver; highDensityForceImproveSolver?: HighDensityForceImproveSolver; highDensityRepairSolver?: Pipeline4HighDensityRepairSolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver3; globalDrcForceImproveSolver?: GlobalDrcForceImproveSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; availableSegmentPointSolver?: AvailableSegmentPointSolver; portPointPathingSolver?: TinyHypergraphPortPointPathingSolver; multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer; uniformPortDistributionSolver?: UniformPortDistributionSolver; traceWidthSolver?: TraceWidthSolver; necessaryCrampedPortPointSolver?: MultiTargetNecessaryCrampedPortPointSolver; componentDetectionSolver?: ComponentDetectionSolver; viaDiameter: number; viaHoleDiameter: number; minTraceWidth: number; effort: number; maxNodeDimension: number; maxNodeRatio: number; minNodeArea: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithEscapeViaLocations?: SimpleRouteJson; srjWithPointPairs?: SimpleRouteJson; originalSrj: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; /** Available segment points after non-component cramped points are filtered. */ sharedEdgeSegmentsWithNecessaryCrampedPortPoints?: SharedEdgeSegment[]; highDensityNodePortPoints?: NodeWithPortPoints[]; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2 | PipelineStep$2)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$2); private setSimpleRouteJson; getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$2]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } type SplitNodesIntoSingleLayerNodeSolverParams = { capacityMeshNodes: CapacityMeshNode[]; sharedEdgeSegments: SharedEdgeSegment[]; }; declare class SplitNodesIntoSingleLayerNodeSolver extends BaseSolver { readonly params: SplitNodesIntoSingleLayerNodeSolverParams; outputNodes: CapacityMeshNode[]; outputSharedEdgeSegments: SharedEdgeSegment[]; private nodeIdByOriginalAndZ; constructor(params: SplitNodesIntoSingleLayerNodeSolverParams); getSolverName(): string; _step(): void; private getSplitNodeId; private splitPortPoint; private splitSharedEdgeSegment; getOutput(): { capacityMeshNodes: CapacityMeshNode[]; sharedEdgeSegments: SharedEdgeSegment[]; }; getConstructorParams(): readonly [SplitNodesIntoSingleLayerNodeSolverParams]; visualize(): GraphicsObject; } interface CapacityMeshSolverOptions$1 { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; effort?: number; maxNodeDimension?: number; maxNodeRatio?: number; minNodeArea?: number; } type PipelineStep$1 BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AutoroutingPipelineSolver8) => ConstructorParameters; onSolved?: (instance: AutoroutingPipelineSolver8) => void; }; declare class AutoroutingPipelineSolver8 extends BaseSolver { srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions$1; preprocessSimpleRouteJsonSolver?: PreprocessSimpleRouteJsonSolver$1; escapeViaLocationSolver?: EscapeViaLocationSolver; netToPointPairsSolver?: NetToPointPairsSolver; nodeSolver?: RectDiffPipeline; nodeDimensionSubdivisionSolver?: NodeDimensionSubdivisionSolver; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; colorMap: Record; highDensityRouteSolver?: HighDensitySolver; highDensityForceImproveSolver?: HighDensityForceImproveSolver; highDensityForceImproveRoutes?: HighDensityRoute$1[]; highDensityRepairSolver?: Pipeline4HighDensityRepairSolver; highDensityRepairRoutes?: HighDensityRoute$1[]; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver3; globalDrcForceImproveSolver?: GlobalDrcForceImproveSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; traceSimplificationSolver?: TraceSimplificationSolver; availableSegmentPointSolver?: AvailableSegmentPointSolver; splitNodesIntoSingleLayerNodeSolver?: SplitNodesIntoSingleLayerNodeSolver; portPointPathingSolver?: TinyHypergraphPortPointPathingSolver; multiSectionPortPointOptimizer?: MultiSectionPortPointOptimizer; uniformPortDistributionSolver?: UniformPortDistributionSolver; traceWidthSolver?: TraceWidthSolver; necessaryCrampedPortPointSolver?: MultiTargetNecessaryCrampedPortPointSolver; viaDiameter: number; viaHoleDiameter: number; minTraceWidth: number; effort: number; maxNodeDimension: number; maxNodeRatio: number; minNodeArea: number; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithEscapeViaLocations?: SimpleRouteJson; srjWithPointPairs?: SimpleRouteJson; originalSrj: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; highDensityNodePortPoints?: NodeWithPortPoints[]; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1 | PipelineStep$1)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions$1); private setSimpleRouteJson; getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions$1]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; private routesOnlyUsePreplacedVias; private getHighDensityNodePortPointsWithAssignableViasFirst; private getPreplacedAssignableViaObstacles; private isFixedPreplacedViaRoute; private getMovableHighDensityRouteIndexes; private getMovableHighDensityRoutes; private mergeMovableHighDensityRoutesBack; getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } /** * Calculate the capacity of a node based on its width * * This capacity corresponds to how many vias the node can fit, tuned for two * layers. * * @param node The node or width to calculate capacity for * @param maxCapacityFactor Optional multiplier to adjust capacity * @returns The calculated capacity */ declare const getTunedTotalCapacity1: (node: CapacityMeshNode | { width: number; height?: number; availableZ?: number[]; }, maxCapacityFactor?: number, opts?: { viaDiameter?: number; obstacleMargin?: number; }) => number; /** * Calculate the optimal subdivision depth to reach a target minimum capacity * @param initialWidth The initial width of the top-level node * @param targetMinCapacity The minimum capacity target (default 0.5) * @param maxDepth Maximum allowed depth (default 10) * @returns The optimal capacity depth */ declare const calculateOptimalCapacityDepth: (initialWidth: number, targetMinCapacity?: number, maxDepth?: number) => number; /** * An in-memory implementation of the CacheProvider interface. * Useful for testing or scenarios where persistence is not required. */ declare class InMemoryCache implements CacheProvider { cacheHitsByPrefix: Record; cacheMissesByPrefix: Record; isSyncCache: boolean; cacheHits: number; cacheMisses: number; cache: Map; /** * Retrieves a cached solution synchronously based on the cache key. * Increments cache hit/miss counters. * @param cacheKey The key to look up in the cache. * @returns The cached solution if found, otherwise undefined. */ getCachedSolutionSync(cacheKey: string): any; /** * Retrieves a cached solution asynchronously. Wraps the synchronous method. * @param cacheKey The key to look up in the cache. * @returns A promise that resolves with the cached solution or undefined. */ getCachedSolution(cacheKey: string): Promise; /** * Stores a solution in the cache synchronously. * Uses structured cloning to store a copy, preventing external modifications. * @param cacheKey The key under which to store the solution. * @param cachedSolution The solution data to cache. */ setCachedSolutionSync(cacheKey: string, cachedSolution: any): void; /** * Stores a solution in the cache asynchronously. Wraps the synchronous method. * @param cacheKey The key under which to store the solution. * @param cachedSolution The solution data to cache. * @returns A promise that resolves when the solution is cached. */ setCachedSolution(cacheKey: string, cachedSolution: any): Promise; /** * Clears the entire cache and resets hit/miss counters. */ clearCache(): void; getAllCacheKeys(): string[]; } /** * A CacheProvider implementation using the browser's localStorage. * Note: localStorage has size limits (typically 5-10MB) and stores data as strings. * Complex objects will be JSON serialized/deserialized. */ declare class LocalStorageCache implements CacheProvider { isSyncCache: boolean; cacheHits: number; cacheMisses: number; cacheHitsByPrefix: Record; cacheMissesByPrefix: Record; constructor(); private getKey; /** * Retrieves a cached solution synchronously from localStorage. * Increments cache hit/miss counters. * @param cacheKey The key to look up in the cache. * @returns The cached solution if found and parsed correctly, otherwise undefined. */ getCachedSolutionSync(cacheKey: string): any; /** * Retrieves a cached solution asynchronously. Wraps the synchronous method. * @param cacheKey The key to look up in the cache. * @returns A promise that resolves with the cached solution or undefined. */ getCachedSolution(cacheKey: string): Promise; /** * Stores a solution in localStorage synchronously. * The solution is JSON stringified before storing. * @param cacheKey The key under which to store the solution. * @param cachedSolution The solution data to cache. */ setCachedSolutionSync(cacheKey: string, cachedSolution: any): void; /** * Stores a solution in the cache asynchronously. Wraps the synchronous method. * @param cacheKey The key under which to store the solution. * @param cachedSolution The solution data to cache. * @returns A promise that resolves when the solution is cached. */ setCachedSolution(cacheKey: string, cachedSolution: any): Promise; /** * Clears all cache entries created by this instance from localStorage * and resets hit/miss counters. */ clearCache(): void; getAllCacheKeys(): string[]; } declare global { var TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE: LocalStorageCache; var TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE: InMemoryCache; } declare function getGlobalLocalStorageCache(): LocalStorageCache; declare function getGlobalInMemoryCache(): InMemoryCache; declare function setupGlobalCaches(): void; interface CapacityMeshNodeSolverOptions { capacityDepth?: number; } /** * This capacity mesh node solver is meant to be used in contexts where vias * aren't allowed, but there may be assignable vias on the PCB as obstacles. * * Behavior: * - Outside assignable obstacles, multi-layer nodes are *always* Z-split into single-layer nodes. * - During mesh subdivision, nodes overlapping with "assignable" obstacles * (obstacle.netIsAssignable === true) are NOT filtered, allowing normal subdivision. * - After the main mesh subdivision is complete: * 1. All nodes overlapping with assignable obstacles are removed * 2. Each assignable obstacle is replaced with a single multi-layer node spanning all layers * - Single-layer nodes that are larger than MAX_SIZE_FOR_SINGLE_LAYER_NODES are XY-subdivided. * - IMPORTANT: the multi-layer nodes created from assignable obstacles are **traversable**, * so we mark `_containsObstacle = false` and `_completelyInsideObstacle = false` on them. */ declare class CapacityMeshNodeSolver_OnlyTraverseLayersInAssignableObstacles extends CapacityMeshNodeSolver2_NodeUnderObstacle { srj: SimpleRouteJson; opts: CapacityMeshNodeSolverOptions; MAX_SIZE_FOR_SINGLE_LAYER_NODES: number; constructor(srj: SimpleRouteJson, opts?: CapacityMeshNodeSolverOptions); private isObstacleAssignable; private getOverlappingAssignableObstacles; shouldNodeBeXYSubdivided(node: CapacityMeshNode): boolean; /** * Filter nodes for obstacles, but skip filtering for assignable obstacles. * Assignable obstacles will be handled separately at the end. */ shouldFilterNodeForObstacle(node: CapacityMeshNode): boolean; /** * Remove nodes inside assignable obstacles and replace with single multi-layer nodes. * The new node's bounds are extended to cover all removed nodes' XY space. */ private insertAssignableObstaclesAsNodes; _step(): void; } /** * Variant of SingleLayerNodeMergerSolver that only merges nodes containing targets. * Nodes without targets are passed through unchanged. */ declare class SingleLayerNodeMergerSolver_OnlyMergeTargets extends BaseSolver { getSolverName(): string; nodeMap: Map; currentBatchNodeIds: CapacityMeshNodeId[]; absorbedNodeIds: Set; nextBatchNodeIds: CapacityMeshNodeId[]; batchHadModifications: boolean; hasComputedAdjacentNodeIds: boolean; newNodes: CapacityMeshNode[]; constructor(nodes: CapacityMeshNode[]); computeAdjacentNodeIdsForFirstBatch(nodes: CapacityMeshNode[]): void; getAdjacentSameLayerUnprocessedNodes(rootNode: CapacityMeshNode): CapacityMeshNode[]; _step(): void; visualize(): GraphicsObject; } /** * This solver merges nodes that represent the same assignable obstacle into a single node. * * For each assignable obstacle: * - Finds all nodes that have _assignedViaObstacle pointing to that obstacle * - Replaces them with a single node representing the bounding box of all removed nodes * - Each step handles one assignable obstacle */ declare class AssignableViaNodeMergerSolver extends BaseSolver { getSolverName(): string; newNodes: CapacityMeshNode[]; obstacleToNodesMap: Map; obstaclesToProcess: Obstacle[]; mergedNodeIds: Set; constructor(nodes: CapacityMeshNode[]); _step(): void; visualize(): GraphicsObject; } interface Point { x: number; y: number; z: number; } declare class SingleSimplifiedPathSolver extends BaseSolver { getSolverName(): string; newRoute: HighDensityIntraNodeRoute$1["route"]; newVias: HighDensityIntraNodeRoute$1["vias"]; headIndex: number; tailIndex: number; inputRoute: HighDensityIntraNodeRoute$1; otherHdRoutes: HighDensityIntraNodeRoute$1[]; obstacles: Obstacle[]; connMap: ConnectivityMap; colorMap: Record; outline?: Array<{ x: number; y: number; }>; constructor(params: { inputRoute: HighDensityIntraNodeRoute$1; otherHdRoutes: HighDensityIntraNodeRoute$1[]; obstacles: Obstacle[]; connMap: ConnectivityMap; colorMap: Record; outline?: Array<{ x: number; y: number; }>; }); getConstructorParams(): { inputRoute: HighDensityIntraNodeRoute$1; otherHdRoutes: HighDensityIntraNodeRoute$1[]; obstacles: Obstacle[]; connMap: Record; colorMap: Record; outline: { x: number; y: number; }[] | undefined; }; get simplifiedRoute(): HighDensityIntraNodeRoute$1; isValidPath(pointsInRoute: Point[]): boolean; _step(): void; getVisualsForNewRouteAndObstacles(): GraphicsObject & Pick, "points" | "lines" | "rects" | "circles">; } declare class MultiSimplifiedPathSolver extends BaseSolver { getSolverName(): string; simplifiedHdRoutes: HighDensityIntraNodeRoute$1[]; currentUnsimplifiedHdRouteIndex: number; activeSubSolver: SingleSimplifiedPathSolver | null; unsimplifiedHdRoutes: HighDensityIntraNodeRoute$1[]; obstacles: Obstacle[]; connMap: ConnectivityMap; colorMap: Record; outline?: Array<{ x: number; y: number; }>; defaultViaDiameter: number; constructor(params: { unsimplifiedHdRoutes: HighDensityIntraNodeRoute$1[]; obstacles: Obstacle[]; connMap?: ConnectivityMap; colorMap?: Record; outline?: Array<{ x: number; y: number; }>; defaultViaDiameter?: number; }); _step(): void; visualize(): GraphicsObject; } interface RouteSection { startIndex: number; endIndex: number; z: number; points: HighDensityRoute["route"]; } declare class SingleRouteUselessViaRemovalSolver extends BaseSolver { getSolverName(): string; obstacleSHI: ObstacleSpatialHashIndex; hdRouteSHI: HighDensityRouteSpatialIndex; unsimplifiedRoute: HighDensityRoute; routeSections: Array; currentSectionIndex: number; TRACE_THICKNESS: number; OBSTACLE_MARGIN: number; ENDPOINT_LAYER_EPSILON: number; constructor(params: { obstacleSHI: ObstacleSpatialHashIndex; hdRouteSHI: HighDensityRouteSpatialIndex; unsimplifiedRoute: HighDensityRoute; }); breakRouteIntoSections(route: HighDensityRoute): never[] | this["routeSections"]; _step(): void; /** * Check if an endpoint (first or last point of the route) can connect * to a different layer. This is only allowed if the obstacles the endpoint * connects to support that layer. */ canEndpointConnectOnLayer(endpointX: number, endpointY: number, targetZ: number): boolean; canSectionMoveToLayer({ currentSection, targetZ, }: { currentSection: RouteSection; targetZ: number; }): boolean; getConstructorParams(): { obstacleSHI: ObstacleSpatialHashIndex; hdRouteSHI: HighDensityRouteSpatialIndex; unsimplifiedRoute: HighDensityIntraNodeRoute; }; getOptimizedHdRoute(): HighDensityRoute; visualize(): GraphicsObject; } interface UselessViaRemovalSolverInput { unsimplifiedHdRoutes: HighDensityRoute$1[]; obstacles: Obstacle[]; colorMap: Record; layerCount: number; } declare class UselessViaRemovalSolver extends BaseSolver { private input; getSolverName(): string; unsimplifiedHdRoutes: HighDensityRoute$1[]; optimizedHdRoutes: HighDensityRoute$1[]; unprocessedRoutes: HighDensityRoute$1[]; activeSubSolver?: SingleRouteUselessViaRemovalSolver | null | undefined; obstacleSHI: ObstacleSpatialHashIndex | null; hdRouteSHI: HighDensityRouteSpatialIndex | null; constructor(input: UselessViaRemovalSolverInput); _step(): void; getOptimizedHdRoutes(): HighDensityRoute$1[] | null; visualize(): GraphicsObject; } type Candidate = { prevCandidate: Candidate | null; node: CapacityMeshNode; f: number; g: number; h: number; }; type AssignableViaCapacityHyperParameters = Partial & { SHUFFLE_SEED?: number; DIRECTIVE_SEED?: number; FORCE_VIA_TRAVEL_CHANCE?: number; FAR_VIA_MIN_DISTANCE?: number; MAX_CLOSEST_VIA_SKIP?: number; MAX_FURTHEST_VIA_SKIP?: number; }; type ConnectionNodePair = { start: CapacityMeshNode; end: CapacityMeshNode; connection: SimpleRouteConnection; }; type SubpathNodePair = { start: CapacityMeshNode; end: CapacityMeshNode; solved: boolean; path?: CapacityMeshNode[]; layer: number; }; type ConnectionPathWithNodes = { connection: SimpleRouteConnection; path: CapacityMeshNode[]; }; /** * See description in the prompt */ declare class AssignableViaCapacityPathingSolver_DirectiveSubOptimal extends BaseSolver { private inputParams; getSolverName(): string; /** * Bias toward greedier choices (f = g + GREEDY_MULTIPLIER * h) */ GREEDY_MULTIPLIER: number; simpleRouteJson: SimpleRouteJson; nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; colorMap: Record; MAX_ITERATIONS: number; hyperParameters: Partial; usedNodeMap: Map; nodeMap: Map; nodeEdgeMap: Map; unprocessedConnectionPairs: ConnectionNodePair[]; solvedRoutes: ConnectionPathWithNodes[]; activeConnectionPair: ConnectionNodePair | null; ogUnprocessedSubpaths: SubpathNodePair[] | null; unprocessedSubpaths: SubpathNodePair[] | null; solvedSubpaths: SubpathNodePair[] | null; activeSubpath: SubpathNodePair | null; viaNodes: CapacityMeshNode[]; closestViaForConnectionStartMap: Map; closestViaForConnectionEndMap: Map; constructor(inputParams: { simpleRouteJson: SimpleRouteJson; nodes: CapacityMeshNode[]; edges: CapacityMeshEdge[]; colorMap?: Record; MAX_ITERATIONS?: number; hyperParameters?: Partial; }); getConstructorParams(): typeof this.inputParams; lastStepOperation: "none" | "dequeueConnectionPair" | "breakConnectionPairIntoSubpaths" | "dequeueSubpath" | "stepSolveSubpath" | "finishedSolvingSubpath" | "finishedSolvingConnectionPair"; /** * Computes and stores the closest via for both start and end of each unprocessed connection pair. * This is used to ensure we don't "steal" a via that's closest to another connection. */ computeClosestViaForAllConnections(): void; _step(): void; queuedCandidateNodes: Candidate[]; visitedNodes: Set; private _dist; stepSolveSubpath(subpath: SubpathNodePair): void; getNeighbors(node: CapacityMeshNode): CapacityMeshNode[]; clearCandidateNodes(): void; computeG(prevCandidate: Candidate, node: CapacityMeshNode, _endGoal: CapacityMeshNode): number; computeH(_prevCandidate: Candidate, node: CapacityMeshNode, endGoal: CapacityMeshNode): number; createSolvedRoute(subpaths: SubpathNodePair[], connectionPair: ConnectionNodePair): ConnectionPathWithNodes; breakConnectionPairIntoSubpaths(connectionPair: ConnectionNodePair): SubpathNodePair[]; getClosestVia(node: CapacityMeshNode): CapacityMeshNode; getFarVia(closestVia: CapacityMeshNode, end: CapacityMeshNode): CapacityMeshNode; getCapacityPaths(): CapacityPath[]; visualize(): GraphicsObject; } type AssignableViaCapacityPathingParams = ConstructorParameters[0]; type HyperParameterOverrides = Partial & { TRACE_ORDERING_SEED?: number; LAYER_TRAVERSAL_REWARD?: number; }; declare class HyperAssignableViaCapacityPathingSolver extends HyperParameterSupervisorSolver { getSolverName(): string; constructorParams: AssignableViaCapacityPathingParams; constructor(opts: AssignableViaCapacityPathingParams); getHyperParameterDefs(): ({ name: string; possibleValues: { SHUFFLE_SEED: number; }[]; } | { name: string; possibleValues: { FORCE_VIA_TRAVEL_CHANCE: number; }[]; })[]; computeG(solver: AssignableViaCapacityPathingSolver_DirectiveSubOptimal): number; computeH(solver: AssignableViaCapacityPathingSolver_DirectiveSubOptimal): number; generateSolver(hyperParameters: HyperParameterOverrides): AssignableViaCapacityPathingSolver_DirectiveSubOptimal; } /** * Creates offboard edges between assignable via obstacles that share * the same `offBoardConnectsTo` net name. These obstacles represent off-board * connection points (like edge connectors) that are logically connected * through external wiring. * * The solver finds all capacity nodes with `_assignedViaObstacle.offBoardConnectsTo`, * groups them by net name, and creates zero-cost offboard edges between * matching nodes. This allows the pathing solver to route through these virtual * connections as if the obstacles were directly connected. */ declare class OffboardCapacityNodeSolver extends BaseSolver { getSolverName(): string; capacityNodes: CapacityMeshNode[]; capacityEdges: CapacityMeshEdge[]; enhancedEdges: CapacityMeshEdge[]; private animationState; private assignableNodes; private shownNodes; private pendingEdges; private createdEdges; private nextEdgeId; private nodeMap; constructor(solverParams: { capacityNodes: CapacityMeshNode[]; capacityEdges: CapacityMeshEdge[]; }); private initializeAssignableNodes; private initializePendingEdges; _step(): void; private createOffboardEdge; visualize(): GraphicsObject; getVirtualOffboardNodes(): CapacityMeshNode[]; getOffboardEdges(): CapacityMeshEdge[]; } /** * Splits capacity paths at offboard edges into separate fragments. * When a path crosses an offboard edge (created by OffboardCapacityNodeSolver), * this solver breaks it into independent path segments. * * Each fragment becomes a separate connection with its own `connectionName` * (e.g., `AD_NET_frag_0`, `AD_NET_frag_1`). The solver also creates new * `SimpleRouteConnection` entries with appropriate `pointsToConnect` - the * original pad location plus a synthetic point at the offboard node. * * This enables downstream solvers to route each fragment independently, * treating them as separate traces that terminate at off-board connection points. */ declare class OffboardPathFragmentSolver extends BaseSolver { getSolverName(): string; private inputPaths; private capacityEdges; private originalConnections; fragmentedPaths: CapacityPath[]; fragmentedConnections: SimpleRouteConnection[]; fragmentedOriginalConnectionNames: Set; private nextFragmentId; private animationState; private currentPath; private currentFragments; private currentFragmentIndex; private nodeMap; constructor({ capacityPaths, capacityEdges, capacityNodes, connections, }: { capacityPaths: CapacityPath[]; capacityEdges: CapacityMeshEdge[]; capacityNodes: CapacityMeshNode[]; connections: SimpleRouteConnection[]; }); _step(): void; private createFragmentConnections; private splitPath; getFragmentedPaths(): CapacityPath[]; getFragmentedConnections(): SimpleRouteConnection[]; getFragmentedOriginalConnectionNames(): Set; visualize(): GraphicsObject; private drawPath; } interface CapacityMeshSolverOptions { capacityDepth?: number; targetMinCapacity?: number; cacheProvider?: CacheProvider | null; } type AutoroutingPipelineSolverOptions = CapacityMeshSolverOptions; type PipelineStep BaseSolver> = { solverName: string; solverClass: T; getConstructorParams: (instance: AssignableAutoroutingPipeline1Solver) => ConstructorParameters; onSolved?: (instance: AssignableAutoroutingPipeline1Solver) => void; }; declare class AssignableAutoroutingPipeline1Solver extends BaseSolver { readonly srj: SimpleRouteJson; readonly opts: CapacityMeshSolverOptions; getSolverName(): string; netToPointPairsSolver?: NetToPointPairsSolver; nodeSolver?: CapacityMeshNodeSolver; nodeTargetMerger?: CapacityNodeTargetMerger; edgeSolver?: CapacityMeshEdgeSolver; initialPathingSolver?: AssignableViaCapacityPathingSolver_DirectiveSubOptimal; initialPathingHyperSolver?: HyperAssignableViaCapacityPathingSolver; pathingOptimizer?: CapacityPathingMultiSectionSolver; edgeToPortSegmentSolver?: CapacityEdgeToPortSegmentSolver; colorMap: Record; segmentToPointSolver?: CapacitySegmentToPointSolver; unravelMultiSectionSolver?: UnravelMultiSectionSolver; segmentToPointOptimizer?: CapacitySegmentPointOptimizer; highDensityRouteSolver?: HighDensitySolver; highDensityStitchSolver?: MultipleHighDensityRouteStitchSolver; singleLayerNodeMerger?: SingleLayerNodeMergerSolver_OnlyMergeTargets; mergeAssignableViaNodes?: AssignableViaNodeMergerSolver; offboardCapacityNodeSolver?: OffboardCapacityNodeSolver; offboardPathFragmentSolver?: OffboardPathFragmentSolver; strawSolver?: StrawSolver; deadEndSolver?: DeadEndSolver; uselessViaRemovalSolver1?: UselessViaRemovalSolver; uselessViaRemovalSolver2?: UselessViaRemovalSolver; multiSimplifiedPathSolver1?: MultiSimplifiedPathSolver; multiSimplifiedPathSolver2?: MultiSimplifiedPathSolver; startTimeOfPhase: Record; endTimeOfPhase: Record; timeSpentOnPhase: Record; activeSubSolver?: BaseSolver | null; connMap: ConnectivityMap; srjWithPointPairs?: SimpleRouteJson; capacityNodes: CapacityMeshNode[] | null; capacityEdges: CapacityMeshEdge[] | null; cacheProvider: CacheProvider | null; pipelineDef: (PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep | PipelineStep)[]; constructor(srj: SimpleRouteJson, opts?: CapacityMeshSolverOptions); getConstructorParams(): readonly [SimpleRouteJson, CapacityMeshSolverOptions]; currentPipelineStepIndex: number; _step(): void; solveUntilPhase(phase: string): void; getCurrentPhase(): string; visualize(): GraphicsObject; /** * A lightweight version of the visualize method that can be used to stream * progress * * We return the most relevant graphic for the stage: * 1. netToPointPairs output * 2. Capacity Planning Output * 3. High Density Route Solver Output, max 200 lines */ preview(): GraphicsObject; _getOutputHdRoutes(): HighDensityRoute$1[]; /** * Returns the SimpleRouteJson with routes converted to SimplifiedPcbTraces */ getOutputSimplifiedPcbTraces(): SimplifiedPcbTraces; getOutputSimpleRouteJson(): SimpleRouteJson; } declare const convertSrjToGraphicsObject: (srj: SimpleRouteJson) => { rects: Rect[]; circles: Circle[]; lines: Line[]; points: Point$5[]; }; type RerouteRectRegion = { shape: "rect"; minX: number; maxX: number; minY: number; maxY: number; }; declare const getRerouteSimpleRouteJson: (simpleRouteJson: SimpleRouteJson, region: RerouteRectRegion) => SimpleRouteJson; declare const reconnectReroutedSimpleRouteJsonRegion: (originalSrj: SimpleRouteJson, reroutedSrj: SimpleRouteJson) => SimpleRouteJson; type FutureConnection = { connectionName: string; rootConnectionName?: string; regionId?: string; points: { x: number; y: number; z: number; }[]; }; /** * Components that make up the g (cost so far) calculation */ type GComponents = { /** Total path distance traveled from start */ distFromStart: number; /** Cumulative weighted penalty for being near obstacles */ weightedMmNearObstacle: number; /** Cumulative weighted penalty for being near edges */ weightedMmNearEdge: number; /** Cumulative weighted penalty for being near future connection start/end points */ weightedMmNearFutureConnectionStartEnd: number; /** Cumulative weighted penalty for being near future connection lines */ weightedMmNearFutureConnectionLine: number; /** Cumulative jumper penalty (includes jumper distance + penalty factor) */ jumperPenalty: number; /** Cumulative penalty for jumper pads near future connections */ jumperPadFutureConnectionPenalty: number; /** Total g value (sum of all components) */ total: number; }; /** * Components that make up the h (heuristic) calculation */ type HComponents = { distanceToGoal: number; obstacleProximity: number; edgeProximity: number; futureConnectionStartEndProximityPenalty: number; futureConnectionLine: number; total: number; /** Stored rates (penalty per mm) for derivative computation */ obstacleProximityRate: number; edgeProximityRate: number; futureConnectionStartEndProximityRate: number; futureConnectionLineRate: number; }; /** * Extended node type that tracks jumper usage */ type JumperNode = Node & { /** If this node was reached via a jumper, this contains jumper info */ jumperEntry?: { x: number; y: number; }; /** Track if this movement is the exit of a jumper */ isJumperExit?: boolean; /** Count of jumpers used to reach this node */ jumperCount?: number; /** Stored g components for debugging/visualization */ gComponents?: GComponents; /** Stored h components for debugging/visualization */ hComponents?: HComponents; }; declare class SingleHighDensityRouteWithJumpersSolver extends BaseSolver { getSolverName(): string; obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[]; bounds: { minX: number; maxX: number; minY: number; maxY: number; }; boundsSize: { width: number; height: number; }; boundsCenter: { x: number; y: number; }; A: { x: number; y: number; z: number; }; B: { x: number; y: number; z: number; }; roundedGoalPosition: { x: number; y: number; z: number; }; straightLineDistance: number; traceThickness: number; obstacleMargin: number; minCellSize: number; cellStep: number; GREEDY_MULTIPLER: number; numRoutes: number; /** Penalty factor for using a jumper (relative to distance) */ JUMPER_PENALTY_FACTOR: number; /** Future connection proximity parameters */ FUTURE_CONNECTION_START_END_PENALTY: number; FUTURE_CONNECTION_START_END_PROXIMITY: number; /** Future connection jumper pad penalty parameters */ FUTURE_CONNECTION_JUMPER_PAD_PROXIMITY: number; FUTURE_CONNECTION_JUMPER_PAD_PENALTY: number; /** Jumper-to-jumper pad proximity penalty parameters */ JUMPER_JUMPER_PAD_PROXIMITY: number; JUMPER_JUMPER_PAD_PENALTY: number; /** Future connection line proximity penalty parameters */ FUTURE_CONNECTION_LINE_PROXIMITY: number; FUTURE_CONNECTION_LINE_PENALTY: number; /** Obstacle proximity penalty parameters (repulsive field) */ OBSTACLE_PROX_PENALTY_FACTOR: number; OBSTACLE_PROX_SIGMA: number; /** Edge proximity penalty parameters */ EDGE_PROX_PENALTY_FACTOR: number; EDGE_PROX_SIGMA: number; /** Whether to allow diagonal movement in pathfinding */ ALLOW_DIAGONAL: boolean; /** Minimum distance traveled before allowing jumper neighbors */ MIN_TRAVEL_BEFORE_JUMPER: number; CELL_SIZE_FACTOR: number; exploredNodes: Set; candidates: SingleRouteCandidatePriorityQueue; connectionName: string; rootConnectionName?: string; regionId?: string; solvedPath: HighDensityIntraNodeRouteWithJumpers | null; futureConnections: FutureConnection[]; hyperParameters: Partial; connMap?: ConnectivityMap; /** For debugging/animating the exploration */ debug_exploredNodesOrdered: string[]; debug_exploredNodeValues: Map; debug_nodesTooCloseToObstacle: Set; debug_nodePathToParentIntersectsObstacle: Set; debugEnabled: boolean; initialNodeGridOffset: { x: number; y: number; }; /** Existing jumpers that act as obstacles */ existingJumpers: Jumper[]; constructor(opts: { connectionName: string; rootConnectionName?: string; regionId?: string; obstacleRoutes: HighDensityIntraNodeRouteWithJumpers[]; minDistBetweenEnteringPoints: number; bounds: { minX: number; maxX: number; minY: number; maxY: number; }; A: { x: number; y: number; z: number; }; B: { x: number; y: number; z: number; }; traceThickness?: number; obstacleMargin?: number; futureConnections?: FutureConnection[]; hyperParameters?: Partial; connMap?: ConnectivityMap; }); handleSimpleCases(): void; get jumperPenaltyDistance(): number; /** * Check if a node is too close to an obstacle trace or jumper */ isNodeTooCloseToObstacle(node: JumperNode, margin?: number): boolean; /** * Check if a node is too close to a jumper's pads * Traces CAN route under the body of the jumper, just not under the pads */ isNodeTooCloseToJumper(node: { x: number; y: number; }, jumper: Jumper, margin: number): boolean; isNodeTooCloseToEdge(node: JumperNode): boolean; doesPathToParentIntersectObstacle(node: JumperNode): boolean; /** * Check if a line segment intersects with a jumper's pads * Segments CAN pass under the jumper body, just not through the pads */ doesSegmentIntersectJumperPads(p1: { x: number; y: number; }, p2: { x: number; y: number; }, jumper: Jumper): boolean; /** * Check if a line segment intersects with an axis-aligned rectangle */ doesSegmentIntersectRect(p1: { x: number; y: number; }, p2: { x: number; y: number; }, center: { x: number; y: number; }, halfWidth: number, halfHeight: number): boolean; /** * Find obstacles between current node and a target position * Returns the obstacle segment(s) that block the direct path */ findObstaclesBetween(from: { x: number; y: number; }, to: { x: number; y: number; }): Array<{ A: { x: number; y: number; }; B: { x: number; y: number; }; }>; computeHComponents(node: JumperNode): HComponents; computeH(node: JumperNode): number; computeGComponents(node: JumperNode): GComponents; computeG(node: JumperNode): number; computeF(g: number, h: number): number; getClosestFutureConnectionPoint(node: JumperNode): { x: number; y: number; z: number; } | null; getFutureConnectionStartEndPenalty(node: JumperNode): number; /** * Calculate penalty for being close to future connection line segments. * This penalty is computed by summing the segment-to-point distance between * the node and all unrouted future connection start-to-end segments. * The penalty helps routes avoid crossing directly over future connection paths. */ getFutureConnectionLinePenalty(node: JumperNode): number; /** * Calculate penalty for jumper pads placed near future connection start/end points. * This disincentivizes placing jumper pads in areas that will be needed for future routing. * The distance is calculated as the minimum distance from either jumper pad to any future connection point. */ getJumperPadFutureConnectionPenalty(node: JumperNode): number; /** * Compute the minimum distance from a node to any obstacle (trace segments and jumper pads) */ getClearanceToObstacles(node: { x: number; y: number; }): number; /** * Compute distance from a point to the nearest jumper pad */ distanceToJumperPads(p: { x: number; y: number; }, j: Jumper): number; /** * Compute distance from a point to an axis-aligned rectangle (0 if inside) */ pointToRectDistance(p: { x: number; y: number; }, c: { x: number; y: number; }, halfW: number, halfH: number): number; /** * Compute minimum distance from a node to the nearest boundary edge */ getClearanceToEdge(node: { x: number; y: number; }): number; /** * Compute the obstacle proximity penalty (repulsive field) * Returns a high value near obstacles, ~0 far away */ getObstacleProximityPenalty(node: JumperNode): number; /** * Compute the edge proximity penalty (repulsive field near boundaries) * Returns a high value near edges, ~0 far away * Penalty is reduced as we approach the goal (which is always on an edge) */ getEdgeProximityPenalty(node: JumperNode): number; getNodeKey(node: JumperNode): string; /** * Calculate potential jumper positions to cross an obstacle */ getJumperNeighbors(node: JumperNode): JumperNode[]; /** * Calculate the exit position for a jumper that clears an obstacle */ calculateJumperExit(entry: JumperNode, obstacle: { A: { x: number; y: number; }; B: { x: number; y: number; }; }, direction: { dx: number; dy: number; }): JumperNode | null; /** * Check if a jumper's pads are too close to obstacle traces */ isJumperTooCloseToTraces(entry: { x: number; y: number; }, exit: { x: number; y: number; }): boolean; /** * Verify that a jumper placement is valid (doesn't overlap with existing jumpers or traces) */ isJumperPlacementValid(entry: JumperNode, exit: JumperNode): boolean; /** * Check if two jumpers overlap */ doJumpersOverlap(j1: Jumper, j2: Jumper): boolean; /** * Get all jumpers in the path to a node */ getJumpersInPath(node: JumperNode): Jumper[]; getNeighbors(node: JumperNode): JumperNode[]; getNodePath(node: JumperNode): JumperNode[]; setSolvedPath(node: JumperNode): void; computeProgress(currentNode: JumperNode, goalDist: number): number; _step(): void; /** * Draw the two pads of an 0603 jumper * Pad dimensions are rotated based on jumper orientation */ private drawJumperPads; visualize(): GraphicsObject; } /** * IntraNodeSolverWithJumpers is designed for single-layer nodes that use * 0603 jumpers to allow traces to jump over each other. * * Unlike the standard IntraNodeRouteSolver which uses vias to change layers, * this solver operates on a single layer and uses physical jumper components * to handle trace crossings. */ declare class IntraNodeSolverWithJumpers extends BaseSolver { getSolverName(): string; nodeWithPortPoints: NodeWithPortPoints; colorMap: Record; unsolvedConnections: { connectionName: string; rootConnectionName?: string; points: { x: number; y: number; z: number; }[]; }[]; totalConnections: number; solvedRoutes: HighDensityIntraNodeRouteWithJumpers[]; failedSubSolvers: SingleHighDensityRouteWithJumpersSolver[]; hyperParameters: Partial; minDistBetweenEnteringPoints: number; traceWidth: number; activeSubSolver: SingleHighDensityRouteWithJumpersSolver | null; lastActiveSubSolver: SingleHighDensityRouteWithJumpersSolver | null; connMap?: ConnectivityMap; get failedSolvers(): SingleHighDensityRouteWithJumpersSolver[]; get activeSolver(): SingleHighDensityRouteWithJumpersSolver | null; constructor(params: { nodeWithPortPoints: NodeWithPortPoints; colorMap?: Record; hyperParameters?: Partial; connMap?: ConnectivityMap; traceWidth?: number; }); getConstructorParams(): { nodeWithPortPoints: NodeWithPortPoints; colorMap: Record; hyperParameters: Partial; connMap: ConnectivityMap | undefined; traceWidth: number; }; computeProgress(): number; _step(): void; /** * Draw the two pads of an 0603 jumper * Pad dimensions are rotated based on jumper orientation */ private drawJumperPads; visualize(): GraphicsObject; } export { AssignableAutoroutingPipeline1Solver, AssignableAutoroutingPipeline2, AssignableAutoroutingPipeline3, AttachProjectedRectsSolver, AutoroutingPipeline1_OriginalUnravel, AutoroutingPipelineSolver4_TinyHypergraph as AutoroutingPipelineSolver, AutoroutingPipelineSolver2_PortPointPathing, AutoroutingPipelineSolver3_HgPortPointPathing, AutoroutingPipelineSolver4_TinyHypergraph as AutoroutingPipelineSolver4, AutoroutingPipelineSolver4_TinyHypergraph, AutoroutingPipelineSolver5_HdCache as AutoroutingPipelineSolver5, AutoroutingPipelineSolver5_HdCache, AutoroutingPipelineSolver6_PolyHypergraph as AutoroutingPipelineSolver6, AutoroutingPipelineSolver6_PolyHypergraph, AutoroutingPipelineSolver7_MultiGraph, AutoroutingPipelineSolver8, type AutoroutingPipelineSolverOptions, type CachableSolver, type CacheProvider, CapacityMeshSolver, CurvyIntraNodeSolver, GrowShrinkHighDensityIntraNodeSolver, type HighDensityIntraNodeRouteWithJumpers, JumperHighDensitySolver as HighDensitySolver, HyperSingleIntraNodeSolver, InMemoryCache, IntraNodeSolverWithJumpers, type Jumper, LocalStorageCache, PolyHighDensitySolver, PolySingleIntraNodeSolver as PolyIntraNodeSolver, PolySingleIntraNodeSolver, ProjectHighDensityToPolygonSolver, type RerouteRectRegion, SingleHighDensityRouteWithJumpersSolver, calculateOptimalCapacityDepth, convertSrjToGraphicsObject, getGlobalInMemoryCache, getGlobalLocalStorageCache, getRerouteSimpleRouteJson, getTunedTotalCapacity1, reconnectReroutedSimpleRouteJsonRegion, setupGlobalCaches };