@tscircuit/fanout-solver 0.0.26 → 0.0.28
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/fanout-solver.ts +54 -13
- package/lib/route-bus.ts +14 -1
- package/package.json +1 -1
package/lib/fanout-solver.ts
CHANGED
|
@@ -1028,8 +1028,31 @@ export class FanoutSolver extends BaseSolver {
|
|
|
1028
1028
|
this.pendingRepairAssignments.push(...repairs)
|
|
1029
1029
|
}
|
|
1030
1030
|
|
|
1031
|
+
private hasCompleteBestAttempt(): boolean {
|
|
1032
|
+
return (
|
|
1033
|
+
this.bestAttempt?.summary.routedConnectionCount ===
|
|
1034
|
+
this.inputSrj.connections.length
|
|
1035
|
+
)
|
|
1036
|
+
}
|
|
1037
|
+
|
|
1038
|
+
private shouldEvaluateGroupedBeam(): boolean {
|
|
1039
|
+
if (this.groupedBeamEvaluated || this.nextAssignmentIndex === 0) {
|
|
1040
|
+
return false
|
|
1041
|
+
}
|
|
1042
|
+
|
|
1043
|
+
const targetedRepairSearchFinished =
|
|
1044
|
+
this.hasCompleteBestAttempt() ||
|
|
1045
|
+
this.pendingRepairAssignments.length === 0 ||
|
|
1046
|
+
this.nextAssignmentIndex >= this.config.maxLayerCombinations
|
|
1047
|
+
|
|
1048
|
+
return targetedRepairSearchFinished
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1031
1051
|
override _step(): void {
|
|
1032
|
-
|
|
1052
|
+
// Try the deterministic assignment and only its targeted repair queue
|
|
1053
|
+
// before paying for the grouped beam. If the beam cannot solve, continue
|
|
1054
|
+
// with the broader generated-assignment search below.
|
|
1055
|
+
if (this.shouldEvaluateGroupedBeam()) {
|
|
1033
1056
|
this.groupedBeamEvaluated = true
|
|
1034
1057
|
let beamAttempt = this.evaluateGroupedBeam(-1)
|
|
1035
1058
|
if (!beamAttempt) {
|
|
@@ -1037,19 +1060,33 @@ export class FanoutSolver extends BaseSolver {
|
|
|
1037
1060
|
}
|
|
1038
1061
|
if (beamAttempt) {
|
|
1039
1062
|
this.attempts.push(beamAttempt.summary)
|
|
1040
|
-
|
|
1063
|
+
if (
|
|
1064
|
+
!this.bestAttempt ||
|
|
1065
|
+
beamAttempt.summary.score < this.bestAttempt.summary.score
|
|
1066
|
+
) {
|
|
1067
|
+
this.bestAttempt = beamAttempt
|
|
1068
|
+
}
|
|
1069
|
+
const bestSummary = this.bestAttempt.summary
|
|
1041
1070
|
this.stats = {
|
|
1042
|
-
assignment:
|
|
1071
|
+
assignment:
|
|
1072
|
+
bestSummary.assignmentIndex < 0
|
|
1073
|
+
? 0
|
|
1074
|
+
: bestSummary.assignmentIndex + 1,
|
|
1043
1075
|
assignmentCount: this.config.maxLayerCombinations,
|
|
1044
|
-
routedBuses: `${
|
|
1045
|
-
routedConnections: `${
|
|
1076
|
+
routedBuses: `${bestSummary.routedBusCount}/${this.preparedBuses.length}`,
|
|
1077
|
+
routedConnections: `${bestSummary.routedConnectionCount}/${this.inputSrj.connections.length}`,
|
|
1046
1078
|
failedBuses: "none",
|
|
1047
|
-
bestScore:
|
|
1079
|
+
bestScore: bestSummary.score,
|
|
1048
1080
|
}
|
|
1049
1081
|
this.completeBestAttemptEndpoints()
|
|
1050
1082
|
this.solved = true
|
|
1051
1083
|
return
|
|
1052
1084
|
}
|
|
1085
|
+
if (this.hasCompleteBestAttempt()) {
|
|
1086
|
+
this.completeBestAttemptEndpoints()
|
|
1087
|
+
this.solved = true
|
|
1088
|
+
return
|
|
1089
|
+
}
|
|
1053
1090
|
}
|
|
1054
1091
|
|
|
1055
1092
|
let assignment: Readonly<Record<string, string>> | undefined
|
|
@@ -1060,13 +1097,19 @@ export class FanoutSolver extends BaseSolver {
|
|
|
1060
1097
|
const preferGeneratedAssignment = this.nextAssignmentIndex % 3 === 0
|
|
1061
1098
|
let candidate: Readonly<Record<string, string>> | undefined
|
|
1062
1099
|
let candidateCameFromRepairQueue = false
|
|
1063
|
-
if (
|
|
1100
|
+
if (!this.groupedBeamEvaluated && this.nextAssignmentIndex > 0) {
|
|
1101
|
+
candidate = this.pendingRepairAssignments.pop()
|
|
1102
|
+
candidateCameFromRepairQueue = candidate !== undefined
|
|
1103
|
+
} else if (preferGeneratedAssignment) {
|
|
1064
1104
|
candidate = this.layerAssignments[this.nextGeneratedAssignmentIndex++]
|
|
1065
1105
|
} else {
|
|
1066
1106
|
candidate = this.pendingRepairAssignments.pop()
|
|
1067
1107
|
candidateCameFromRepairQueue = candidate !== undefined
|
|
1068
1108
|
}
|
|
1069
|
-
if (
|
|
1109
|
+
if (
|
|
1110
|
+
!candidate &&
|
|
1111
|
+
(this.groupedBeamEvaluated || this.nextAssignmentIndex === 0)
|
|
1112
|
+
) {
|
|
1070
1113
|
candidate = preferGeneratedAssignment
|
|
1071
1114
|
? this.pendingRepairAssignments.pop()
|
|
1072
1115
|
: this.layerAssignments[this.nextGeneratedAssignmentIndex++]
|
|
@@ -1081,12 +1124,9 @@ export class FanoutSolver extends BaseSolver {
|
|
|
1081
1124
|
if (this.evaluatedAssignmentKeys.has(candidateKey)) continue
|
|
1082
1125
|
assignment = candidate
|
|
1083
1126
|
}
|
|
1127
|
+
if (!assignment && !this.groupedBeamEvaluated) return
|
|
1084
1128
|
if (!assignment) {
|
|
1085
|
-
if (
|
|
1086
|
-
this.bestAttempt &&
|
|
1087
|
-
this.bestAttempt.summary.routedConnectionCount ===
|
|
1088
|
-
this.inputSrj.connections.length
|
|
1089
|
-
) {
|
|
1129
|
+
if (this.hasCompleteBestAttempt()) {
|
|
1090
1130
|
this.completeBestAttemptEndpoints()
|
|
1091
1131
|
this.solved = true
|
|
1092
1132
|
} else {
|
|
@@ -1131,6 +1171,7 @@ export class FanoutSolver extends BaseSolver {
|
|
|
1131
1171
|
bestScore: this.bestAttempt.summary.score,
|
|
1132
1172
|
}
|
|
1133
1173
|
if (
|
|
1174
|
+
this.groupedBeamEvaluated &&
|
|
1134
1175
|
attempt.summary.routedConnectionCount === this.inputSrj.connections.length
|
|
1135
1176
|
) {
|
|
1136
1177
|
this.completeBestAttemptEndpoints()
|
package/lib/route-bus.ts
CHANGED
|
@@ -293,11 +293,23 @@ function getTrackCandidates(params: {
|
|
|
293
293
|
function getPreferredTrack(params: {
|
|
294
294
|
bus: PreparedBus
|
|
295
295
|
connection: PreparedConnection
|
|
296
|
+
traceWidth: number
|
|
296
297
|
}): number {
|
|
297
|
-
|
|
298
|
+
const preferredTrack = getPerpendicularAxis(
|
|
298
299
|
params.connection.exitTargetPoint ?? params.connection.targetPoint,
|
|
299
300
|
params.bus.direction,
|
|
300
301
|
)
|
|
302
|
+
const boundaryMinimum = isHorizontal(params.bus.direction)
|
|
303
|
+
? params.bus.sharedBoundary.minY
|
|
304
|
+
: params.bus.sharedBoundary.minX
|
|
305
|
+
const boundaryMaximum = isHorizontal(params.bus.direction)
|
|
306
|
+
? params.bus.sharedBoundary.maxY
|
|
307
|
+
: params.bus.sharedBoundary.maxX
|
|
308
|
+
|
|
309
|
+
return Math.max(
|
|
310
|
+
boundaryMinimum + params.traceWidth / 2,
|
|
311
|
+
Math.min(boundaryMaximum - params.traceWidth / 2, preferredTrack),
|
|
312
|
+
)
|
|
301
313
|
}
|
|
302
314
|
|
|
303
315
|
function getLegacyPreferredTrack(params: {
|
|
@@ -1373,6 +1385,7 @@ export function routeBusAlternatives(
|
|
|
1373
1385
|
getPreferredTrack({
|
|
1374
1386
|
bus,
|
|
1375
1387
|
connection: preparedConnection,
|
|
1388
|
+
traceWidth,
|
|
1376
1389
|
}),
|
|
1377
1390
|
getLegacyPreferredTrack({
|
|
1378
1391
|
bus,
|