diff --git a/lib/outside-in-partial-rip-tiny-hypergraph-solver.ts b/lib/outside-in-partial-rip-tiny-hypergraph-solver.ts index 6582ef3..40e8fc9 100644 --- a/lib/outside-in-partial-rip-tiny-hypergraph-solver.ts +++ b/lib/outside-in-partial-rip-tiny-hypergraph-solver.ts @@ -1040,8 +1040,14 @@ export class OutsideInPartialRipTinyHyperGraphSolver extends DistanceAwareTinyHy this.RIP_THRESHOLD_RAMP_ATTEMPTS, this.PARTIAL_RIP_MAX_ATTEMPTS, ) + const ripThresholdRampAttempts = Math.max( + 0, + this.RIP_THRESHOLD_RAMP_ATTEMPTS, + ) const ripThresholdProgress = - maxRipAttempts <= 0 ? 1 : Math.min(1, state.ripCount / maxRipAttempts) + ripThresholdRampAttempts <= 0 + ? 1 + : Math.min(1, state.ripCount / ripThresholdRampAttempts) const currentRipThreshold = this.RIP_THRESHOLD_START + (this.RIP_THRESHOLD_END - this.RIP_THRESHOLD_START) * ripThresholdProgress diff --git a/tests/outside-in-partial-rip-tiny-hypergraph-solver.test.ts b/tests/outside-in-partial-rip-tiny-hypergraph-solver.test.ts index dcb2a05..8d1b2b5 100644 --- a/tests/outside-in-partial-rip-tiny-hypergraph-solver.test.ts +++ b/tests/outside-in-partial-rip-tiny-hypergraph-solver.test.ts @@ -171,6 +171,22 @@ test("the configured warmup performs a whole-graph rerip first", () => { expect(solver.stats.partialRipCount ?? 0).toBe(0) }) +test("the partial-rip cap does not compress the threshold ramp", () => { + const solver = createLinearSolver(24, { + RIP_THRESHOLD_START: 0.05, + RIP_THRESHOLD_END: 0.8, + RIP_THRESHOLD_RAMP_ATTEMPTS: 10, + PARTIAL_RIP_MAX_ATTEMPTS: 1, + }) + solver.state.ripCount = 1 + solver.state.regionIntersectionCaches[3]!.existingRegionCost = 1 + + solver.onAllRoutesRouted() + + expect(solver.solved).toBe(true) + expect(solver.stats.currentRipThreshold).toBeCloseTo(0.125) +}) + test("complexity-aware selection activates only at its route-count gate", () => { const belowGateSolver = createLinearSolver(24, { PARTIAL_RIP_MAX_ATTEMPTS: 0,