@tscircuit/capacity-autorouter 0.0.86 → 0.0.88

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/dist/index.d.ts CHANGED
@@ -114,6 +114,12 @@ declare class BaseSolver {
114
114
  getConstructorParams(): void;
115
115
  solve(): void;
116
116
  visualize(): GraphicsObject;
117
+ /**
118
+ * Called when the solver is about to fail, but we want to see if we have an
119
+ * "acceptable" or "passable" solution. Mostly used for optimizers that
120
+ * have an aggressive early stopping criterion.
121
+ */
122
+ tryFinalAcceptance(): void;
117
123
  /**
118
124
  * A lightweight version of the visualize method that can be used to stream
119
125
  * progress
@@ -422,6 +428,7 @@ interface HighDensityHyperParameters {
422
428
  SEGMENTS_PER_POLYLINE: number;
423
429
  BOUNDARY_PADDING: number;
424
430
  ITERATION_PENALTY: number;
431
+ MINIMUM_FINAL_ACCEPTANCE_GAP?: number;
425
432
  }
426
433
 
427
434
  type Node = {
@@ -762,11 +769,13 @@ declare class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<
762
769
  SEGMENTS_PER_POLYLINE: number;
763
770
  BOUNDARY_PADDING: number;
764
771
  ITERATION_PENALTY?: undefined;
772
+ MINIMUM_FINAL_ACCEPTANCE_GAP?: undefined;
765
773
  } | {
766
774
  MULTI_HEAD_POLYLINE_SOLVER: boolean;
767
775
  SEGMENTS_PER_POLYLINE: number;
768
776
  BOUNDARY_PADDING: number;
769
777
  ITERATION_PENALTY: number;
778
+ MINIMUM_FINAL_ACCEPTANCE_GAP: number;
770
779
  })[];
771
780
  })[];
772
781
  computeG(solver: IntraNodeRouteSolver): number;
@@ -1581,6 +1590,8 @@ declare class CapacityPathingMultiSectionSolver extends BaseSolver {
1581
1590
  endingScore: number;
1582
1591
  endingHighestNodePf: number;
1583
1592
  }>;
1593
+ cacheHits: number;
1594
+ cacheMisses: number;
1584
1595
  };
1585
1596
  OPTIMIZATION_SCHEDULE: {
1586
1597
  MAX_ATTEMPTS_PER_NODE: number;
package/dist/index.js CHANGED
@@ -67,6 +67,9 @@ var BaseSolver = class {
67
67
  this.failed = true;
68
68
  throw e;
69
69
  }
70
+ if (!this.solved && this.iterations > this.MAX_ITERATIONS) {
71
+ this.tryFinalAcceptance();
72
+ }
70
73
  if (!this.solved && this.iterations > this.MAX_ITERATIONS) {
71
74
  this.error = `${this.constructor.name} ran out of iterations`;
72
75
  console.error(this.error);
@@ -97,6 +100,13 @@ var BaseSolver = class {
97
100
  circles: []
98
101
  };
99
102
  }
103
+ /**
104
+ * Called when the solver is about to fail, but we want to see if we have an
105
+ * "acceptable" or "passable" solution. Mostly used for optimizers that
106
+ * have an aggressive early stopping criterion.
107
+ */
108
+ tryFinalAcceptance() {
109
+ }
100
110
  /**
101
111
  * A lightweight version of the visualize method that can be used to stream
102
112
  * progress
@@ -8172,6 +8182,21 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
8172
8182
  });
8173
8183
  return minGapsToOtherConnectionsValid && allPointsWithinBounds;
8174
8184
  }
8185
+ // ------------------------------------------------------------------
8186
+ // Try accepting the best candidate even if normal solving failed.
8187
+ // ------------------------------------------------------------------
8188
+ tryFinalAcceptance() {
8189
+ const minGapTarget = this.hyperParameters?.MINIMUM_FINAL_ACCEPTANCE_GAP ?? void 0;
8190
+ if (minGapTarget === void 0 || this.lastCandidate === null || this.lastCandidate.minGaps.length === 0)
8191
+ return;
8192
+ const minGapAchieved = Math.min(...this.lastCandidate.minGaps);
8193
+ if (minGapAchieved >= minGapTarget) {
8194
+ this.solved = true;
8195
+ this._setSolvedRoutes();
8196
+ return;
8197
+ }
8198
+ return;
8199
+ }
8175
8200
  _step() {
8176
8201
  if (this.phase === "setup") {
8177
8202
  this.setupInitialPolyLines();
@@ -8180,6 +8205,8 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
8180
8205
  }
8181
8206
  const currentCandidate = this.candidates.shift();
8182
8207
  if (!currentCandidate) {
8208
+ this.tryFinalAcceptance();
8209
+ if (this.solved) return;
8183
8210
  this.failed = true;
8184
8211
  this.error = "No candidates left";
8185
8212
  return;
@@ -8413,6 +8440,8 @@ var MultiHeadPolyLineIntraNodeSolver2 = class extends MultiHeadPolyLineIntraNode
8413
8440
  }
8414
8441
  const currentCandidate = this.candidates.shift();
8415
8442
  if (!currentCandidate) {
8443
+ this.tryFinalAcceptance();
8444
+ if (this.solved) return;
8416
8445
  this.failed = true;
8417
8446
  return;
8418
8447
  }
@@ -9063,7 +9092,8 @@ var HyperSingleIntraNodeSolver = class extends HyperParameterSupervisorSolver {
9063
9092
  SEGMENTS_PER_POLYLINE: 6,
9064
9093
  BOUNDARY_PADDING: -0.05,
9065
9094
  // Allow vias/traces outside the boundary
9066
- ITERATION_PENALTY: 1e4
9095
+ ITERATION_PENALTY: 1e4,
9096
+ MINIMUM_FINAL_ACCEPTANCE_GAP: 1e-3
9067
9097
  }
9068
9098
  ]
9069
9099
  }
@@ -13522,6 +13552,7 @@ var CachedHyperCapacityPathingSingleSectionSolver = class extends HyperCapacityP
13522
13552
  });
13523
13553
  const terminals = {};
13524
13554
  const cacheSpaceToRealConnectionId = /* @__PURE__ */ new Map();
13555
+ const connectionPairMap = /* @__PURE__ */ new Map();
13525
13556
  for (const conn of this.constructorParams.sectionConnectionTerminals) {
13526
13557
  const cacheStartNodeId = realToCacheSpaceNodeIdMap.get(conn.startNodeId);
13527
13558
  const cacheEndNodeId = realToCacheSpaceNodeIdMap.get(conn.endNodeId);
@@ -13529,7 +13560,10 @@ var CachedHyperCapacityPathingSingleSectionSolver = class extends HyperCapacityP
13529
13560
  cacheStartNodeId,
13530
13561
  cacheEndNodeId
13531
13562
  ].sort();
13532
- const cacheSpaceConnectionId = `${sortedStartId}->${sortedEndId}`;
13563
+ const pairKey = `${sortedStartId}->${sortedEndId}`;
13564
+ const pairIndex = connectionPairMap.get(pairKey) ?? 0;
13565
+ connectionPairMap.set(pairKey, pairIndex + 1);
13566
+ const cacheSpaceConnectionId = `${sortedStartId}->${sortedEndId}::${pairIndex}`;
13533
13567
  terminals[cacheSpaceConnectionId] = {
13534
13568
  start: sortedStartId,
13535
13569
  end: sortedEndId
@@ -13796,9 +13830,11 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
13796
13830
  endingHighestNodePf: 0,
13797
13831
  sectionAttempts: 0
13798
13832
  })
13799
- )
13833
+ ),
13834
+ cacheHits: 0,
13835
+ cacheMisses: 0
13800
13836
  };
13801
- this.MAX_ITERATIONS = 1e7;
13837
+ this.MAX_ITERATIONS = params.MAX_ITERATIONS ?? 1e7;
13802
13838
  this.cacheProvider = params.cacheProvider;
13803
13839
  this.simpleRouteJson = params.simpleRouteJson;
13804
13840
  this.nodes = params.nodes;
@@ -13943,6 +13979,13 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
13943
13979
  );
13944
13980
  }
13945
13981
  this.sectionSolver.step();
13982
+ if (this.sectionSolver.failed || this.sectionSolver.solved) {
13983
+ if (this.sectionSolver.cacheHit) {
13984
+ this.stats.cacheHits++;
13985
+ } else {
13986
+ this.stats.cacheMisses++;
13987
+ }
13988
+ }
13946
13989
  if (this.sectionSolver.failed) {
13947
13990
  console.warn(
13948
13991
  `Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`