diff --git a/lib/core.ts b/lib/core.ts index d334dc5..34f7e49 100644 --- a/lib/core.ts +++ b/lib/core.ts @@ -1361,11 +1361,21 @@ export class TinyHyperGraphSolver extends BaseSolver { state.currentRouteId = undefined } + protected isEstablishingInitialSolution(): boolean { + return !this.bestSolvedStateSnapshot + } + computeG(currentCandidate: Candidate, neighborPortId: PortId): number { const { state } = this const nextRegionId = currentCandidate.nextRegionId + if (this.isEstablishingInitialSolution()) { + return ( + currentCandidate.g + (this.problem.portPenalty?.[neighborPortId] ?? 0) + ) + } + const regionCache = state.regionIntersectionCaches[nextRegionId] const segmentGeometry = this.populateSegmentGeometryScratch( nextRegionId, diff --git a/lib/section-solver/index.ts b/lib/section-solver/index.ts index e66f4a1..91166de 100644 --- a/lib/section-solver/index.ts +++ b/lib/section-solver/index.ts @@ -684,6 +684,10 @@ class TinyHyperGraphSectionSearchSolver extends TinyHyperGraphSolver { return super.getStartingNextRegionId(routeId, startingPortId) } + protected override isEstablishingInitialSolution(): boolean { + return false + } + override resetRoutingStateForRerip() { if (!this.fixedSnapshot) { super.resetRoutingStateForRerip() diff --git a/tests/solver/single-layer-region-cost.test.ts b/tests/solver/single-layer-region-cost.test.ts index e3414fe..e74f5d9 100644 --- a/tests/solver/single-layer-region-cost.test.ts +++ b/tests/solver/single-layer-region-cost.test.ts @@ -45,12 +45,21 @@ const createProblem = (): TinyHyperGraphProblem => ({ regionNetId: new Int32Array(2).fill(-1), }) -const getCrossingCost = (regionAvailableZMask: number, portZ: number) => { +const getCrossingCost = ( + regionAvailableZMask: number, + portZ: number, + hasInitialSolution = true, +) => { const solver = new TinyHyperGraphSolver( createTopology(regionAvailableZMask, portZ), createProblem(), ) + if (hasInitialSolution) { + solver.state.unroutedRoutes = [] + solver.onAllRoutesRouted() + } + solver.state.currentRouteNetId = 0 solver.appendSegmentToRegionCache(0, 0, 2) @@ -67,6 +76,10 @@ const getCrossingCost = (regionAvailableZMask: number, portZ: number) => { ) } +test("initial solution routing ignores same-layer crossing costs", () => { + expect(getCrossingCost(1 << 0, 0, false)).toBe(0) +}) + test("same-layer crossings in known single-layer regions are rejected as candidates", () => { const topLayerCrossingCost = getCrossingCost(1 << 0, 0) const bottomLayerCrossingCost = getCrossingCost(1 << 1, 1)