@tscircuit/capacity-autorouter 0.0.87 → 0.0.89

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
@@ -35,8 +35,10 @@ interface SimpleRouteConnection {
35
35
  x: number;
36
36
  y: number;
37
37
  layer: string;
38
+ pointId?: string;
38
39
  pcb_port_id?: string;
39
40
  }>;
41
+ externallyConnectedPointIds?: string[][];
40
42
  }
41
43
  interface SimplifiedPcbTrace {
42
44
  type: "pcb_trace";
@@ -114,6 +116,12 @@ declare class BaseSolver {
114
116
  getConstructorParams(): void;
115
117
  solve(): void;
116
118
  visualize(): GraphicsObject;
119
+ /**
120
+ * Called when the solver is about to fail, but we want to see if we have an
121
+ * "acceptable" or "passable" solution. Mostly used for optimizers that
122
+ * have an aggressive early stopping criterion.
123
+ */
124
+ tryFinalAcceptance(): void;
117
125
  /**
118
126
  * A lightweight version of the visualize method that can be used to stream
119
127
  * progress
@@ -422,6 +430,7 @@ interface HighDensityHyperParameters {
422
430
  SEGMENTS_PER_POLYLINE: number;
423
431
  BOUNDARY_PADDING: number;
424
432
  ITERATION_PENALTY: number;
433
+ MINIMUM_FINAL_ACCEPTANCE_GAP?: number;
425
434
  }
426
435
 
427
436
  type Node = {
@@ -762,11 +771,13 @@ declare class HyperSingleIntraNodeSolver extends HyperParameterSupervisorSolver<
762
771
  SEGMENTS_PER_POLYLINE: number;
763
772
  BOUNDARY_PADDING: number;
764
773
  ITERATION_PENALTY?: undefined;
774
+ MINIMUM_FINAL_ACCEPTANCE_GAP?: undefined;
765
775
  } | {
766
776
  MULTI_HEAD_POLYLINE_SOLVER: boolean;
767
777
  SEGMENTS_PER_POLYLINE: number;
768
778
  BOUNDARY_PADDING: number;
769
779
  ITERATION_PENALTY: number;
780
+ MINIMUM_FINAL_ACCEPTANCE_GAP: number;
770
781
  })[];
771
782
  })[];
772
783
  computeG(solver: IntraNodeRouteSolver): 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
  }
@@ -9585,16 +9615,34 @@ var NetToPointPairsSolver = class extends BaseSolver {
9585
9615
  return;
9586
9616
  }
9587
9617
  const connection = this.unprocessedConnections.pop();
9618
+ const externalGroups = connection.externallyConnectedPointIds ?? [];
9619
+ const pointIdToGroup = /* @__PURE__ */ new Map();
9620
+ externalGroups.forEach(
9621
+ (group, idx) => group.forEach((pid) => pointIdToGroup.set(pid, idx))
9622
+ );
9623
+ const areExternallyConnected = (a, b) => {
9624
+ if (!a.pointId || !b.pointId) return false;
9625
+ const g1 = pointIdToGroup.get(a.pointId);
9626
+ const g2 = pointIdToGroup.get(b.pointId);
9627
+ return g1 !== void 0 && g1 === g2;
9628
+ };
9588
9629
  if (connection.pointsToConnect.length === 2) {
9630
+ if (areExternallyConnected(
9631
+ connection.pointsToConnect[0],
9632
+ connection.pointsToConnect[1]
9633
+ )) {
9634
+ return;
9635
+ }
9589
9636
  this.newConnections.push(connection);
9590
9637
  return;
9591
9638
  }
9592
9639
  const edges = buildMinimumSpanningTree(connection.pointsToConnect);
9593
- for (let i = 0; i < edges.length; i++) {
9594
- const edge = edges[i];
9640
+ let mstIdx = 0;
9641
+ for (const edge of edges) {
9642
+ if (areExternallyConnected(edge.from, edge.to)) continue;
9595
9643
  this.newConnections.push({
9596
9644
  pointsToConnect: [edge.from, edge.to],
9597
- name: `${connection.name}_mst${i}`
9645
+ name: `${connection.name}_mst${mstIdx++}`
9598
9646
  });
9599
9647
  }
9600
9648
  }