Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
512 changes: 512 additions & 0 deletions lib/DuplicateCongestedPortSolver.ts

Large diffs are not rendered by default.

312 changes: 311 additions & 1 deletion lib/core.ts

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
export * from "./core"
export * from "./DuplicateCongestedPortSolver"
export * from "./poly"
export * from "./bus-solver"
export * from "./region-graph"
Expand Down
27 changes: 26 additions & 1 deletion lib/section-solver/TinyHyperGraphSectionPipelineSolver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,11 +47,14 @@ const DEFAULT_SOLVE_GRAPH_OPTIONS: TinyHyperGraphSolverOptions = {
RIP_THRESHOLD_RAMP_ATTEMPTS: 5,
}

const DEFAULT_SECTION_SOLVER_MAX_ITERATIONS = 50_000
const DEFAULT_SECTION_PIPELINE_MAX_ITERATIONS = 200_000

const DEFAULT_SECTION_SOLVER_OPTIONS: TinyHyperGraphSectionSolverOptions = {
DISTANCE_TO_COST: 0.05,
RIP_THRESHOLD_RAMP_ATTEMPTS: 16,
RIP_CONGESTION_REGION_COST_FACTOR: 0.1,
MAX_ITERATIONS: 1e6,
MAX_ITERATIONS: DEFAULT_SECTION_SOLVER_MAX_ITERATIONS,
MAX_RIPS_WITHOUT_MAX_REGION_COST_IMPROVEMENT: 6,
EXTRA_RIPS_AFTER_BEATING_BASELINE_MAX_REGION_COST: Number.POSITIVE_INFINITY,
}
Expand Down Expand Up @@ -120,6 +123,10 @@ const createProblemWithPortSectionMask = (
routeEndPort: new Int32Array(problem.routeEndPort),
routeNet: new Int32Array(problem.routeNet),
regionNetId: new Int32Array(problem.regionNetId),
portPenalty:
problem.portPenalty === undefined
? undefined
: new Float64Array(problem.portPenalty),
})

const getSectionMaskCandidates = (
Expand Down Expand Up @@ -317,6 +324,11 @@ export class TinyHyperGraphSectionPipelineSolver extends BasePipelineSolver<Tiny
selectedSectionCandidateLabel?: string
selectedSectionCandidateFamily?: TinyHyperGraphSectionCandidateFamily

constructor(inputProblem: TinyHyperGraphSectionPipelineInput) {
super(inputProblem)
this.MAX_ITERATIONS = DEFAULT_SECTION_PIPELINE_MAX_ITERATIONS
}

loadHyperGraph(serializedHyperGraph: SerializedHyperGraph): {
topology: TinyHyperGraphTopology
problem: TinyHyperGraphProblem
Expand Down Expand Up @@ -495,4 +507,17 @@ export class TinyHyperGraphSectionPipelineSolver extends BasePipelineSolver<Tiny
null
)
}

override tryFinalAcceptance() {
if (this.getStageOutput<SerializedHyperGraph>("solveGraph")) {
this.stats = {
...this.stats,
acceptedSolveGraphOutputOnSectionPipelineTimeout: true,
}
this.activeSubSolver = undefined
this.solved = true
this.failed = false
this.error = null
}
}
}
55 changes: 50 additions & 5 deletions lib/section-solver/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,10 @@ const createSectionRoutePlans = (
routeEndPort,
routeNet: new Int32Array(problem.routeNet),
regionNetId: new Int32Array(problem.regionNetId),
portPenalty:
problem.portPenalty === undefined
? undefined
: new Float64Array(problem.portPenalty),
},
routePlans,
activeRouteIds,
Expand Down Expand Up @@ -834,12 +838,25 @@ class TinyHyperGraphSectionSearchSolver extends TinyHyperGraphSolver {
}

override tryFinalAcceptance() {
if (!this.bestSnapshot) {
super.tryFinalAcceptance()
if (this.bestSnapshot) {
this.restoreBestState()
this.solved = true
return
}

this.restoreBestState()
if (this.fixedSnapshot) {
restoreSolvedStateSnapshot(this, this.fixedSnapshot)
}
this.state.currentRouteId = undefined
this.state.currentRouteNetId = undefined
this.state.unroutedRoutes = [...this.activeRouteIds]
this.state.candidateQueue.clear()
this.resetCandidateBestCosts()
this.state.goalPortId = -1
this.stats = {
...this.stats,
acceptedFixedSectionStateOnTimeout: true,
}
this.solved = true
}

Expand Down Expand Up @@ -878,6 +895,8 @@ export class TinyHyperGraphSectionSolver extends BaseSolver {
override MAX_ITERATIONS = 1e6
STATIC_REACHABILITY_PRECHECK = false
STATIC_REACHABILITY_PRECHECK_MAX_HOPS = 16
ACCEPT_BEST_SOLUTION_ON_TIMEOUT = true
GREEDY_FINAL_ROUTE_ITERS = 4

constructor(
public topology: TinyHyperGraphTopology,
Expand Down Expand Up @@ -975,8 +994,18 @@ export class TinyHyperGraphSectionSolver extends BaseSolver {
}

if (this.sectionSolver.failed) {
this.error = this.sectionSolver.error
this.failed = true
this.optimizedSolver = this.baselineSolver
this.stats = {
...this.stats,
initialMaxRegionCost: this.baselineSummary.maxRegionCost,
initialTotalRegionCost: this.baselineSummary.totalRegionCost,
finalMaxRegionCost: this.baselineSummary.maxRegionCost,
finalTotalRegionCost: this.baselineSummary.totalRegionCost,
optimized: false,
sectionSearchFailedFallbackToBaseline: true,
sectionSearchError: this.sectionSolver.error,
}
this.solved = true
return
}

Expand Down Expand Up @@ -1012,6 +1041,22 @@ export class TinyHyperGraphSectionSolver extends BaseSolver {
this.solved = true
}

override tryFinalAcceptance() {
this.optimizedSolver = this.baselineSolver
this.stats = {
...this.stats,
initialMaxRegionCost: this.baselineSummary.maxRegionCost,
initialTotalRegionCost: this.baselineSummary.totalRegionCost,
finalMaxRegionCost: this.baselineSummary.maxRegionCost,
finalTotalRegionCost: this.baselineSummary.totalRegionCost,
optimized: false,
sectionSolverTimeoutFallbackToBaseline: true,
}
this.solved = true
this.failed = false
this.error = null
}

getSolvedSolver(): TinyHyperGraphSolver {
if (!this.solved || this.failed || !this.optimizedSolver) {
throw new Error(
Expand Down
18 changes: 12 additions & 6 deletions pages/port-chokepoint.page.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,18 @@
import type { SerializedHyperGraph } from "@tscircuit/hypergraph"
import { loadSerializedHyperGraph } from "lib/compat/loadSerializedHyperGraph"
import { TinyHyperGraphSolver } from "lib/index"
import { DuplicateCongestedPortSolver, TinyHyperGraphSolver } from "lib/index"
import { portChokepointFixture } from "../tests/fixtures/port-chokepoint.fixture"
import { Debugger } from "./components/Debugger"

const createSolver = (serializedHyperGraph: SerializedHyperGraph) => {
const { topology, problem } = loadSerializedHyperGraph(serializedHyperGraph)
const duplicateCongestedPortSolver = new DuplicateCongestedPortSolver(
serializedHyperGraph,
)
duplicateCongestedPortSolver.solve()
const { topology, problem } = loadSerializedHyperGraph(
duplicateCongestedPortSolver.getOutput(),
)

return new TinyHyperGraphSolver(topology, problem, {
MAX_ITERATIONS: 20_000,
STATIC_REACHABILITY_PRECHECK: false,
Expand All @@ -18,10 +25,9 @@ export default function PortChokepointPage() {
<div className="rounded border border-slate-300 bg-white p-3 text-sm text-slate-700">
Port chokepoint repro: <code>connection-a</code> routes from the top
left endpoint to the top right endpoint, while <code>connection-b</code>{" "}
routes from the bottom left endpoint to the bottom right endpoint. Both
nets must pass through the single <code>left-center-choke</code> and{" "}
<code>center-right-choke</code> ports, so after one route claims the
corridor the other route has no valid port-disjoint path.
routes from the bottom left endpoint to the bottom right endpoint. The
page first runs <code>DuplicateCongestedPortSolver</code>, then routes
the repaired topology with the strict core solver.
</div>
<div className="min-h-0 flex-1 overflow-hidden rounded border border-slate-300 bg-white">
<Debugger
Expand Down
4 changes: 4 additions & 0 deletions scripts/benchmarking/hg07-section-benchmark.ts
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,10 @@ const createProblemWithPortSectionMask = (
routeEndPort: new Int32Array(problem.routeEndPort),
routeNet: new Int32Array(problem.routeNet),
regionNetId: new Int32Array(problem.regionNetId),
portPenalty:
problem.portPenalty === undefined
? undefined
: new Float64Array(problem.portPenalty),
})

const getSectionMaskCandidates = (
Expand Down
Loading
Loading