@tscircuit/capacity-autorouter 0.0.55 → 0.0.57
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 +51 -38
- package/dist/index.js +811 -167
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -47,6 +47,7 @@ var BaseSolver = class {
|
|
|
47
47
|
activeSubSolver;
|
|
48
48
|
failedSubSolvers;
|
|
49
49
|
timeToSolve;
|
|
50
|
+
stats = {};
|
|
50
51
|
/** DO NOT OVERRIDE! Override _step() instead */
|
|
51
52
|
step() {
|
|
52
53
|
if (this.solved) return;
|
|
@@ -65,6 +66,9 @@ var BaseSolver = class {
|
|
|
65
66
|
console.error(this.error);
|
|
66
67
|
this.failed = true;
|
|
67
68
|
}
|
|
69
|
+
if ("computeProgress" in this) {
|
|
70
|
+
this.progress = this.computeProgress();
|
|
71
|
+
}
|
|
68
72
|
}
|
|
69
73
|
_step() {
|
|
70
74
|
}
|
|
@@ -2902,7 +2906,7 @@ var CapacitySegmentToPointSolver = class extends BaseSolver {
|
|
|
2902
2906
|
}
|
|
2903
2907
|
};
|
|
2904
2908
|
|
|
2905
|
-
// node_modules/@tscircuit/math-utils/dist/chunk-
|
|
2909
|
+
// node_modules/@tscircuit/math-utils/dist/chunk-3453HRP7.js
|
|
2906
2910
|
function doSegmentsIntersect(p1, q1, p2, q2) {
|
|
2907
2911
|
const o1 = orientation(p1, q1, p2);
|
|
2908
2912
|
const o2 = orientation(p1, q1, q2);
|
|
@@ -2941,6 +2945,27 @@ function distance(p1, p2) {
|
|
|
2941
2945
|
const dy = p1.y - p2.y;
|
|
2942
2946
|
return Math.sqrt(dx * dx + dy * dy);
|
|
2943
2947
|
}
|
|
2948
|
+
function getSegmentIntersection(a, b, u, v) {
|
|
2949
|
+
const dx1 = b.x - a.x;
|
|
2950
|
+
const dy1 = b.y - a.y;
|
|
2951
|
+
const dx2 = v.x - u.x;
|
|
2952
|
+
const dy2 = v.y - u.y;
|
|
2953
|
+
const dx3 = a.x - u.x;
|
|
2954
|
+
const dy3 = a.y - u.y;
|
|
2955
|
+
const denominator = dx1 * dy2 - dy1 * dx2;
|
|
2956
|
+
if (Math.abs(denominator) < 1e-10) {
|
|
2957
|
+
return null;
|
|
2958
|
+
}
|
|
2959
|
+
const t = (dy3 * dx2 - dx3 * dy2) / denominator;
|
|
2960
|
+
const s = (dx1 * dy3 - dy1 * dx3) / denominator;
|
|
2961
|
+
const epsilon = 1e-9;
|
|
2962
|
+
if (t >= -epsilon && t <= 1 + epsilon && s >= -epsilon && s <= 1 + epsilon) {
|
|
2963
|
+
const intersectionX = a.x + t * dx1;
|
|
2964
|
+
const intersectionY = a.y + t * dy1;
|
|
2965
|
+
return { x: intersectionX, y: intersectionY };
|
|
2966
|
+
}
|
|
2967
|
+
return null;
|
|
2968
|
+
}
|
|
2944
2969
|
|
|
2945
2970
|
// node_modules/@tscircuit/math-utils/dist/chunk-MHHTZHOJ.js
|
|
2946
2971
|
function getBoundingBox(box) {
|
|
@@ -2974,7 +2999,7 @@ function clamp(value, min, max) {
|
|
|
2974
2999
|
return Math.max(min, Math.min(max, value));
|
|
2975
3000
|
}
|
|
2976
3001
|
|
|
2977
|
-
// node_modules/@tscircuit/math-utils/dist/chunk-
|
|
3002
|
+
// node_modules/@tscircuit/math-utils/dist/chunk-FWQGMQBW.js
|
|
2978
3003
|
function segmentToSegmentMinDistance(a, b, u, v) {
|
|
2979
3004
|
if (a.x === b.x && a.y === b.y) {
|
|
2980
3005
|
return pointToSegmentDistance(a, u, v);
|
|
@@ -3053,6 +3078,14 @@ function pointToSegmentClosestPoint(p, a, b) {
|
|
|
3053
3078
|
return closestPoint;
|
|
3054
3079
|
}
|
|
3055
3080
|
|
|
3081
|
+
// node_modules/@tscircuit/math-utils/dist/chunk-SLG2OU3P.js
|
|
3082
|
+
function midpoint(p1, p2) {
|
|
3083
|
+
return {
|
|
3084
|
+
x: (p1.x + p2.x) / 2,
|
|
3085
|
+
y: (p1.y + p2.y) / 2
|
|
3086
|
+
};
|
|
3087
|
+
}
|
|
3088
|
+
|
|
3056
3089
|
// lib/data-structures/SingleRouteCandidatePriorityQueue.ts
|
|
3057
3090
|
var SingleRouteCandidatePriorityQueue = class {
|
|
3058
3091
|
heap = [];
|
|
@@ -4008,12 +4041,15 @@ var HyperParameterSupervisorSolver = class extends BaseSolver {
|
|
|
4008
4041
|
}
|
|
4009
4042
|
return bestSolver;
|
|
4010
4043
|
}
|
|
4044
|
+
getFailureMessage() {
|
|
4045
|
+
return "All solvers failed in hyper solver.";
|
|
4046
|
+
}
|
|
4011
4047
|
_step() {
|
|
4012
4048
|
if (!this.supervisedSolvers) this.initializeSolvers();
|
|
4013
4049
|
const supervisedSolver = this.getSupervisedSolverWithBestFitness();
|
|
4014
4050
|
if (!supervisedSolver) {
|
|
4015
4051
|
this.failed = true;
|
|
4016
|
-
this.error =
|
|
4052
|
+
this.error = this.getFailureMessage();
|
|
4017
4053
|
return;
|
|
4018
4054
|
}
|
|
4019
4055
|
for (let i = 0; i < this.MIN_SUBSTEPS; i++) {
|
|
@@ -6133,6 +6169,23 @@ var SingleTransitionCrossingRouteSolver = class extends BaseSolver {
|
|
|
6133
6169
|
}
|
|
6134
6170
|
};
|
|
6135
6171
|
|
|
6172
|
+
// lib/utils/getPortPairs.ts
|
|
6173
|
+
var getPortPairMap = (nodeWithPortPoints) => {
|
|
6174
|
+
const portPairMap = /* @__PURE__ */ new Map();
|
|
6175
|
+
nodeWithPortPoints.portPoints.forEach((portPoint) => {
|
|
6176
|
+
if (!portPairMap.has(portPoint.connectionName)) {
|
|
6177
|
+
portPairMap.set(portPoint.connectionName, {
|
|
6178
|
+
start: portPoint,
|
|
6179
|
+
end: null,
|
|
6180
|
+
connectionName: portPoint.connectionName
|
|
6181
|
+
});
|
|
6182
|
+
} else {
|
|
6183
|
+
portPairMap.get(portPoint.connectionName).end = portPoint;
|
|
6184
|
+
}
|
|
6185
|
+
});
|
|
6186
|
+
return portPairMap;
|
|
6187
|
+
};
|
|
6188
|
+
|
|
6136
6189
|
// lib/utils/generateColorMapFromNodeWithPortPoints.ts
|
|
6137
6190
|
var generateColorMapFromNodeWithPortPoints = (nodeWithPortPoints, connMap) => {
|
|
6138
6191
|
const colorMap = {};
|
|
@@ -6142,6 +6195,320 @@ var generateColorMapFromNodeWithPortPoints = (nodeWithPortPoints, connMap) => {
|
|
|
6142
6195
|
return colorMap;
|
|
6143
6196
|
};
|
|
6144
6197
|
|
|
6198
|
+
// lib/solvers/ViaPossibilitiesSolver/ViaPossibilitiesSolver2.ts
|
|
6199
|
+
var ViaPossibilitiesSolver2 = class extends BaseSolver {
|
|
6200
|
+
bounds;
|
|
6201
|
+
maxViaCount;
|
|
6202
|
+
portPairMap;
|
|
6203
|
+
colorMap;
|
|
6204
|
+
nodeWidth;
|
|
6205
|
+
availableZ;
|
|
6206
|
+
hyperParameters;
|
|
6207
|
+
VIA_INTERSECTION_BUFFER_DISTANCE = 0.05;
|
|
6208
|
+
PLACEHOLDER_WALL_BUFFER_DISTANCE = 0.1;
|
|
6209
|
+
NEW_HEAD_WALL_BUFFER_DISTANCE = 0.05;
|
|
6210
|
+
unprocessedConnections;
|
|
6211
|
+
completedPaths = /* @__PURE__ */ new Map();
|
|
6212
|
+
placeholderPaths = /* @__PURE__ */ new Map();
|
|
6213
|
+
currentHead;
|
|
6214
|
+
currentConnectionName;
|
|
6215
|
+
currentPath;
|
|
6216
|
+
constructor({
|
|
6217
|
+
nodeWithPortPoints,
|
|
6218
|
+
colorMap,
|
|
6219
|
+
hyperParameters
|
|
6220
|
+
}) {
|
|
6221
|
+
super();
|
|
6222
|
+
this.MAX_ITERATIONS = 1e5;
|
|
6223
|
+
this.colorMap = colorMap ?? generateColorMapFromNodeWithPortPoints(nodeWithPortPoints);
|
|
6224
|
+
this.maxViaCount = 5;
|
|
6225
|
+
this.bounds = getBoundsFromNodeWithPortPoints(nodeWithPortPoints);
|
|
6226
|
+
this.nodeWidth = this.bounds.maxX - this.bounds.minX;
|
|
6227
|
+
this.portPairMap = getPortPairMap(nodeWithPortPoints);
|
|
6228
|
+
this.stats.solutionsFound = 0;
|
|
6229
|
+
this.availableZ = nodeWithPortPoints.availableZ ?? [0, 1];
|
|
6230
|
+
this.hyperParameters = hyperParameters ?? {
|
|
6231
|
+
SHUFFLE_SEED: 0
|
|
6232
|
+
};
|
|
6233
|
+
this.unprocessedConnections = Array.from(this.portPairMap.keys()).sort();
|
|
6234
|
+
if (hyperParameters?.SHUFFLE_SEED) {
|
|
6235
|
+
this.unprocessedConnections = cloneAndShuffleArray(
|
|
6236
|
+
this.unprocessedConnections,
|
|
6237
|
+
hyperParameters.SHUFFLE_SEED
|
|
6238
|
+
);
|
|
6239
|
+
}
|
|
6240
|
+
const nodeCenterX = (this.bounds.minX + this.bounds.maxX) / 2;
|
|
6241
|
+
const nodeCenterY = (this.bounds.minY + this.bounds.maxY) / 2;
|
|
6242
|
+
for (const [connectionName, { start: start2, end }] of this.portPairMap.entries()) {
|
|
6243
|
+
if (start2.z === end.z) {
|
|
6244
|
+
const isVertical = Math.abs(start2.x - end.x) < 1e-9;
|
|
6245
|
+
const isHorizontal = Math.abs(start2.y - end.y) < 1e-9;
|
|
6246
|
+
if (isVertical || isHorizontal) {
|
|
6247
|
+
this.placeholderPaths.set(connectionName, [
|
|
6248
|
+
start2,
|
|
6249
|
+
this._padByPlaceholderWallBuffer(start2),
|
|
6250
|
+
this._padByPlaceholderWallBuffer(end),
|
|
6251
|
+
end
|
|
6252
|
+
]);
|
|
6253
|
+
} else {
|
|
6254
|
+
this.placeholderPaths.set(connectionName, [start2, end]);
|
|
6255
|
+
}
|
|
6256
|
+
} else {
|
|
6257
|
+
const midX = (start2.x + end.x) / 2;
|
|
6258
|
+
const midY = (start2.y + end.y) / 2;
|
|
6259
|
+
const midStart = this._padByPlaceholderWallBuffer({
|
|
6260
|
+
x: midX,
|
|
6261
|
+
y: midY,
|
|
6262
|
+
z: start2.z
|
|
6263
|
+
});
|
|
6264
|
+
const midEnd = this._padByPlaceholderWallBuffer({
|
|
6265
|
+
x: midX,
|
|
6266
|
+
y: midY,
|
|
6267
|
+
z: end.z
|
|
6268
|
+
});
|
|
6269
|
+
this.placeholderPaths.set(connectionName, [
|
|
6270
|
+
start2,
|
|
6271
|
+
this._padByPlaceholderWallBuffer(start2),
|
|
6272
|
+
midStart,
|
|
6273
|
+
midEnd,
|
|
6274
|
+
this._padByPlaceholderWallBuffer(end),
|
|
6275
|
+
end
|
|
6276
|
+
]);
|
|
6277
|
+
}
|
|
6278
|
+
}
|
|
6279
|
+
this.currentConnectionName = this.unprocessedConnections.pop();
|
|
6280
|
+
const start = this.portPairMap.get(this.currentConnectionName).start;
|
|
6281
|
+
this.currentHead = this._padByNewHeadWallBuffer(start);
|
|
6282
|
+
this.currentPath = [start, this.currentHead];
|
|
6283
|
+
this.placeholderPaths.delete(this.currentConnectionName);
|
|
6284
|
+
}
|
|
6285
|
+
_padByNewHeadWallBuffer(point) {
|
|
6286
|
+
return {
|
|
6287
|
+
x: clamp(
|
|
6288
|
+
point.x,
|
|
6289
|
+
this.bounds.minX + this.NEW_HEAD_WALL_BUFFER_DISTANCE,
|
|
6290
|
+
this.bounds.maxX - this.NEW_HEAD_WALL_BUFFER_DISTANCE
|
|
6291
|
+
),
|
|
6292
|
+
y: clamp(
|
|
6293
|
+
point.y,
|
|
6294
|
+
this.bounds.minY + this.NEW_HEAD_WALL_BUFFER_DISTANCE,
|
|
6295
|
+
this.bounds.maxY - this.NEW_HEAD_WALL_BUFFER_DISTANCE
|
|
6296
|
+
),
|
|
6297
|
+
z: point.z
|
|
6298
|
+
};
|
|
6299
|
+
}
|
|
6300
|
+
_padByPlaceholderWallBuffer(point) {
|
|
6301
|
+
return {
|
|
6302
|
+
x: clamp(
|
|
6303
|
+
point.x,
|
|
6304
|
+
this.bounds.minX + this.PLACEHOLDER_WALL_BUFFER_DISTANCE,
|
|
6305
|
+
this.bounds.maxX - this.PLACEHOLDER_WALL_BUFFER_DISTANCE
|
|
6306
|
+
),
|
|
6307
|
+
y: clamp(
|
|
6308
|
+
point.y,
|
|
6309
|
+
this.bounds.minY + this.PLACEHOLDER_WALL_BUFFER_DISTANCE,
|
|
6310
|
+
this.bounds.maxY - this.PLACEHOLDER_WALL_BUFFER_DISTANCE
|
|
6311
|
+
),
|
|
6312
|
+
z: point.z
|
|
6313
|
+
};
|
|
6314
|
+
}
|
|
6315
|
+
_step() {
|
|
6316
|
+
if (this.solved) return;
|
|
6317
|
+
const targetEnd = this.portPairMap.get(this.currentConnectionName).end;
|
|
6318
|
+
const proposedSegment = [this.currentHead, targetEnd];
|
|
6319
|
+
let closestIntersection = null;
|
|
6320
|
+
let intersectedSegmentZ = null;
|
|
6321
|
+
const checkIntersectionsWithPathMap = (pathMap) => {
|
|
6322
|
+
for (const path of pathMap.values()) {
|
|
6323
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
6324
|
+
const segment = [path[i], path[i + 1]];
|
|
6325
|
+
if (segment[0].x === segment[1].x && segment[0].y === segment[1].y) {
|
|
6326
|
+
continue;
|
|
6327
|
+
}
|
|
6328
|
+
if (segment[0].z !== this.currentHead.z) {
|
|
6329
|
+
continue;
|
|
6330
|
+
}
|
|
6331
|
+
const intersection = getSegmentIntersection(
|
|
6332
|
+
proposedSegment[0],
|
|
6333
|
+
proposedSegment[1],
|
|
6334
|
+
segment[0],
|
|
6335
|
+
segment[1]
|
|
6336
|
+
);
|
|
6337
|
+
if (intersection) {
|
|
6338
|
+
const distToIntersection = distance(this.currentHead, intersection);
|
|
6339
|
+
if (distToIntersection < 1e-6) continue;
|
|
6340
|
+
if (!closestIntersection || distToIntersection < closestIntersection.dist) {
|
|
6341
|
+
closestIntersection = {
|
|
6342
|
+
point: intersection,
|
|
6343
|
+
dist: distToIntersection
|
|
6344
|
+
};
|
|
6345
|
+
intersectedSegmentZ = segment[0].z;
|
|
6346
|
+
}
|
|
6347
|
+
}
|
|
6348
|
+
}
|
|
6349
|
+
}
|
|
6350
|
+
};
|
|
6351
|
+
checkIntersectionsWithPathMap(this.completedPaths);
|
|
6352
|
+
checkIntersectionsWithPathMap(this.placeholderPaths);
|
|
6353
|
+
const needsZChange = this.currentHead.z !== targetEnd.z;
|
|
6354
|
+
if (closestIntersection) {
|
|
6355
|
+
let viaXY;
|
|
6356
|
+
const distToIntersection = closestIntersection.dist;
|
|
6357
|
+
if (distToIntersection < this.VIA_INTERSECTION_BUFFER_DISTANCE) {
|
|
6358
|
+
viaXY = midpoint(this.currentHead, closestIntersection.point);
|
|
6359
|
+
} else {
|
|
6360
|
+
const intersectionPoint = closestIntersection.point;
|
|
6361
|
+
const vectorX = intersectionPoint.x - this.currentHead.x;
|
|
6362
|
+
const vectorY = intersectionPoint.y - this.currentHead.y;
|
|
6363
|
+
const ratio = (distToIntersection - this.VIA_INTERSECTION_BUFFER_DISTANCE) / distToIntersection;
|
|
6364
|
+
viaXY = {
|
|
6365
|
+
x: this.currentHead.x + vectorX * ratio,
|
|
6366
|
+
y: this.currentHead.y + vectorY * ratio
|
|
6367
|
+
};
|
|
6368
|
+
}
|
|
6369
|
+
const nextZ = this.availableZ.find((z) => z !== intersectedSegmentZ);
|
|
6370
|
+
if (nextZ === void 0) {
|
|
6371
|
+
console.error("Could not determine next Z level for via placement!");
|
|
6372
|
+
this.failed = true;
|
|
6373
|
+
return;
|
|
6374
|
+
}
|
|
6375
|
+
const viaPoint1 = { ...viaXY, z: this.currentHead.z };
|
|
6376
|
+
const viaPoint2 = { ...viaXY, z: nextZ };
|
|
6377
|
+
this.currentPath.push(viaPoint1, viaPoint2);
|
|
6378
|
+
this.currentHead = viaPoint2;
|
|
6379
|
+
} else if (needsZChange) {
|
|
6380
|
+
let viaXY;
|
|
6381
|
+
const distToTarget = distance(this.currentHead, targetEnd);
|
|
6382
|
+
if (distToTarget < this.VIA_INTERSECTION_BUFFER_DISTANCE) {
|
|
6383
|
+
viaXY = midpoint(this.currentHead, targetEnd);
|
|
6384
|
+
} else {
|
|
6385
|
+
const vectorX = targetEnd.x - this.currentHead.x;
|
|
6386
|
+
const vectorY = targetEnd.y - this.currentHead.y;
|
|
6387
|
+
const ratio = (distToTarget - this.VIA_INTERSECTION_BUFFER_DISTANCE) / distToTarget;
|
|
6388
|
+
viaXY = {
|
|
6389
|
+
x: this.currentHead.x + vectorX * ratio,
|
|
6390
|
+
y: this.currentHead.y + vectorY * ratio
|
|
6391
|
+
};
|
|
6392
|
+
}
|
|
6393
|
+
const nextZ = targetEnd.z;
|
|
6394
|
+
const viaPoint1 = { ...viaXY, z: this.currentHead.z };
|
|
6395
|
+
const viaPoint2 = { ...viaXY, z: nextZ };
|
|
6396
|
+
this.currentPath.push(viaPoint1, viaPoint2);
|
|
6397
|
+
this.currentHead = viaPoint2;
|
|
6398
|
+
} else {
|
|
6399
|
+
this.currentPath.push(targetEnd);
|
|
6400
|
+
this.completedPaths.set(this.currentConnectionName, this.currentPath);
|
|
6401
|
+
if (this.unprocessedConnections.length === 0) {
|
|
6402
|
+
this.solved = true;
|
|
6403
|
+
this.stats.solutionsFound = 1;
|
|
6404
|
+
} else {
|
|
6405
|
+
this.currentConnectionName = this.unprocessedConnections.pop();
|
|
6406
|
+
const { start } = this.portPairMap.get(this.currentConnectionName);
|
|
6407
|
+
this.currentHead = this._padByNewHeadWallBuffer(start);
|
|
6408
|
+
this.currentPath = [start, this.currentHead];
|
|
6409
|
+
this.placeholderPaths.delete(this.currentConnectionName);
|
|
6410
|
+
}
|
|
6411
|
+
}
|
|
6412
|
+
}
|
|
6413
|
+
visualize() {
|
|
6414
|
+
const graphics = {
|
|
6415
|
+
points: [],
|
|
6416
|
+
lines: [],
|
|
6417
|
+
circles: [],
|
|
6418
|
+
rects: [],
|
|
6419
|
+
title: "Via Possibilities Solver State",
|
|
6420
|
+
coordinateSystem: "cartesian"
|
|
6421
|
+
};
|
|
6422
|
+
const colorMap = this.colorMap;
|
|
6423
|
+
graphics.lines.push({
|
|
6424
|
+
points: [
|
|
6425
|
+
{ x: this.bounds.minX, y: this.bounds.minY },
|
|
6426
|
+
{ x: this.bounds.maxX, y: this.bounds.minY },
|
|
6427
|
+
{ x: this.bounds.maxX, y: this.bounds.maxY },
|
|
6428
|
+
{ x: this.bounds.minX, y: this.bounds.maxY },
|
|
6429
|
+
{ x: this.bounds.minX, y: this.bounds.minY }
|
|
6430
|
+
],
|
|
6431
|
+
strokeColor: "gray",
|
|
6432
|
+
strokeWidth: 0.01
|
|
6433
|
+
});
|
|
6434
|
+
for (const [connectionName, { start, end }] of this.portPairMap.entries()) {
|
|
6435
|
+
const color = this.colorMap[connectionName] ?? "black";
|
|
6436
|
+
graphics.points.push({
|
|
6437
|
+
x: start.x,
|
|
6438
|
+
y: start.y,
|
|
6439
|
+
color,
|
|
6440
|
+
label: `Port: ${connectionName} Start (z${start.z})`
|
|
6441
|
+
});
|
|
6442
|
+
graphics.points.push({
|
|
6443
|
+
x: end.x,
|
|
6444
|
+
y: end.y,
|
|
6445
|
+
color,
|
|
6446
|
+
label: `Port: ${connectionName} End (z${end.z})`
|
|
6447
|
+
});
|
|
6448
|
+
}
|
|
6449
|
+
const drawPath = (pathMap, labelPrefix) => {
|
|
6450
|
+
for (const [connectionName, path] of pathMap.entries()) {
|
|
6451
|
+
const color = colorMap[connectionName] ?? "black";
|
|
6452
|
+
for (let i = 0; i < path.length - 1; i++) {
|
|
6453
|
+
const p1 = path[i];
|
|
6454
|
+
const p2 = path[i + 1];
|
|
6455
|
+
if (p1.x === p2.x && p1.y === p2.y && p1.z !== p2.z) {
|
|
6456
|
+
graphics.circles.push({
|
|
6457
|
+
center: { x: p1.x, y: p1.y },
|
|
6458
|
+
radius: 0.3,
|
|
6459
|
+
// Diameter 0.6
|
|
6460
|
+
fill: safeTransparentize(color, 0.5),
|
|
6461
|
+
label: `${labelPrefix}: ${connectionName} Via (z${p1.z}->z${p2.z})`
|
|
6462
|
+
});
|
|
6463
|
+
} else {
|
|
6464
|
+
graphics.lines.push({
|
|
6465
|
+
points: [p1, p2],
|
|
6466
|
+
strokeColor: safeTransparentize(color, 0.5),
|
|
6467
|
+
strokeDash: p1.z === 0 ? void 0 : [0.1, 0.1],
|
|
6468
|
+
strokeWidth: 0.1,
|
|
6469
|
+
label: `${labelPrefix}: ${connectionName} (z${p1.z})`
|
|
6470
|
+
});
|
|
6471
|
+
}
|
|
6472
|
+
}
|
|
6473
|
+
}
|
|
6474
|
+
};
|
|
6475
|
+
drawPath(this.placeholderPaths, "Placeholder");
|
|
6476
|
+
drawPath(this.completedPaths, "Completed");
|
|
6477
|
+
if (this.currentPath && this.currentPath.length > 0) {
|
|
6478
|
+
const color = colorMap[this.currentConnectionName] ?? "orange";
|
|
6479
|
+
for (let i = 0; i < this.currentPath.length - 1; i++) {
|
|
6480
|
+
const p1 = this.currentPath[i];
|
|
6481
|
+
const p2 = this.currentPath[i + 1];
|
|
6482
|
+
if (p1.x === p2.x && p1.y === p2.y && p1.z !== p2.z) {
|
|
6483
|
+
graphics.circles.push({
|
|
6484
|
+
center: { x: p1.x, y: p1.y },
|
|
6485
|
+
radius: 0.3,
|
|
6486
|
+
fill: safeTransparentize(color, 0.5),
|
|
6487
|
+
label: `Current: ${this.currentConnectionName} Via (z${p1.z}->z${p2.z})`
|
|
6488
|
+
});
|
|
6489
|
+
} else {
|
|
6490
|
+
graphics.lines.push({
|
|
6491
|
+
points: [p1, p2],
|
|
6492
|
+
strokeColor: safeTransparentize(color, 0.5),
|
|
6493
|
+
strokeWidth: 0.15,
|
|
6494
|
+
// Thicker
|
|
6495
|
+
strokeDash: "2,2",
|
|
6496
|
+
// Dashed
|
|
6497
|
+
label: `Current: ${this.currentConnectionName} (z${p1.z})`
|
|
6498
|
+
});
|
|
6499
|
+
}
|
|
6500
|
+
}
|
|
6501
|
+
graphics.points.push({
|
|
6502
|
+
x: this.currentHead.x,
|
|
6503
|
+
y: this.currentHead.y,
|
|
6504
|
+
color: "green",
|
|
6505
|
+
label: `Current Head: ${this.currentConnectionName} (z${this.currentHead.z})`
|
|
6506
|
+
});
|
|
6507
|
+
}
|
|
6508
|
+
return graphics;
|
|
6509
|
+
}
|
|
6510
|
+
};
|
|
6511
|
+
|
|
6145
6512
|
// lib/utils/getIntraNodeCrossings.ts
|
|
6146
6513
|
var getIntraNodeCrossings = (node) => {
|
|
6147
6514
|
let numSameLayerCrossings = 0;
|
|
@@ -6262,10 +6629,13 @@ var Vertex = class {
|
|
|
6262
6629
|
y;
|
|
6263
6630
|
out;
|
|
6264
6631
|
// Outgoing half-edge indices
|
|
6632
|
+
connectionNames;
|
|
6633
|
+
// Names of connections passing through this vertex
|
|
6265
6634
|
constructor(x, y) {
|
|
6266
6635
|
this.x = x;
|
|
6267
6636
|
this.y = y;
|
|
6268
6637
|
this.out = [];
|
|
6638
|
+
this.connectionNames = /* @__PURE__ */ new Set();
|
|
6269
6639
|
}
|
|
6270
6640
|
};
|
|
6271
6641
|
var HalfEdge = class {
|
|
@@ -6349,9 +6719,17 @@ function getCentroidsFromInnerBoxIntersections(rectangle, userSegments) {
|
|
|
6349
6719
|
return t1 - t2;
|
|
6350
6720
|
});
|
|
6351
6721
|
for (let k = 0; k < list.length - 1; ++k) {
|
|
6352
|
-
const
|
|
6353
|
-
const
|
|
6354
|
-
|
|
6722
|
+
const p1 = list[k];
|
|
6723
|
+
const p2 = list[k + 1];
|
|
6724
|
+
const v1 = getVertexId(p1);
|
|
6725
|
+
const v2 = getVertexId(p2);
|
|
6726
|
+
if (v1 !== v2) {
|
|
6727
|
+
undirectedEdges.push([v1, v2]);
|
|
6728
|
+
if (s.connectionName) {
|
|
6729
|
+
vertices[v1].connectionNames.add(s.connectionName);
|
|
6730
|
+
vertices[v2].connectionNames.add(s.connectionName);
|
|
6731
|
+
}
|
|
6732
|
+
}
|
|
6355
6733
|
}
|
|
6356
6734
|
}
|
|
6357
6735
|
const halfEdges = [];
|
|
@@ -6408,8 +6786,11 @@ function getCentroidsFromInnerBoxIntersections(rectangle, userSegments) {
|
|
|
6408
6786
|
if (c) {
|
|
6409
6787
|
centroids.push(c);
|
|
6410
6788
|
faces.push({
|
|
6411
|
-
vertices: poly.map((
|
|
6412
|
-
|
|
6789
|
+
vertices: poly.map((v) => ({
|
|
6790
|
+
x: v.x,
|
|
6791
|
+
y: v.y,
|
|
6792
|
+
connectionNames: v.connectionNames.size > 0 ? v.connectionNames : void 0
|
|
6793
|
+
})),
|
|
6413
6794
|
centroid: c
|
|
6414
6795
|
});
|
|
6415
6796
|
}
|
|
@@ -6995,6 +7376,7 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
|
|
|
6995
7376
|
obstacleMargin = 0.1;
|
|
6996
7377
|
traceWidth = 0.15;
|
|
6997
7378
|
availableZ = [];
|
|
7379
|
+
uniqueConnections = 0;
|
|
6998
7380
|
lastCandidate = null;
|
|
6999
7381
|
maxViaCount;
|
|
7000
7382
|
minViaCount;
|
|
@@ -7022,6 +7404,7 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
|
|
|
7022
7404
|
const uniqueConnections = new Set(
|
|
7023
7405
|
this.nodeWithPortPoints.portPoints.map((pp) => pp.connectionName)
|
|
7024
7406
|
).size;
|
|
7407
|
+
this.uniqueConnections = uniqueConnections;
|
|
7025
7408
|
const { numSameLayerCrossings, numTransitions } = getIntraNodeCrossings(
|
|
7026
7409
|
this.nodeWithPortPoints
|
|
7027
7410
|
);
|
|
@@ -7030,11 +7413,6 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
|
|
|
7030
7413
|
Math.floor(areaInsideNode / areaPerVia),
|
|
7031
7414
|
Math.ceil(uniqueConnections * 1.5)
|
|
7032
7415
|
);
|
|
7033
|
-
if (uniqueConnections > 5) {
|
|
7034
|
-
this.failed = true;
|
|
7035
|
-
this.error = `Limit is currently set to 6 unique connections, ${uniqueConnections} found`;
|
|
7036
|
-
return;
|
|
7037
|
-
}
|
|
7038
7416
|
if (this.minViaCount > this.SEGMENTS_PER_POLYLINE * (uniqueConnections / 2)) {
|
|
7039
7417
|
this.failed = true;
|
|
7040
7418
|
this.error = `Not possible to solve problem with given SEGMENTS_PER_POLYLINE (${this.SEGMENTS_PER_POLYLINE}), atleast ${this.minViaCount} vias are required`;
|
|
@@ -7773,7 +8151,7 @@ var MultiHeadPolyLineIntraNodeSolver = class extends BaseSolver {
|
|
|
7773
8151
|
strokeColor: segmentColor,
|
|
7774
8152
|
strokeWidth: this.traceWidth,
|
|
7775
8153
|
// TODO: Use actual trace thickness from HighDensityRoute?
|
|
7776
|
-
strokeDash: !isLayer0 ?
|
|
8154
|
+
strokeDash: !isLayer0 ? [0.15, 0.15] : void 0,
|
|
7777
8155
|
// Dashed for layers > 0
|
|
7778
8156
|
label: `${polyLine.connectionName} segment (z=${segmentLayer})`
|
|
7779
8157
|
});
|
|
@@ -8259,6 +8637,191 @@ var MultiHeadPolyLineIntraNodeSolver2 = class extends MultiHeadPolyLineIntraNode
|
|
|
8259
8637
|
}
|
|
8260
8638
|
};
|
|
8261
8639
|
|
|
8640
|
+
// lib/solvers/HighDensitySolver/MultiHeadPolyLineIntraNodeSolver/MultiHeadPolyLineIntraNodeSolver3_ViaPossibilitiesSolverIntegration.ts
|
|
8641
|
+
var hashPolyLines = (polyLines) => {
|
|
8642
|
+
return polyLines.flatMap(
|
|
8643
|
+
(pl) => `${pl.connectionName}-${pl.mPoints.map((mp) => `${mp.x.toFixed(2)},${mp.y.toFixed(2)},${mp.z1},${mp.z2}`)}`
|
|
8644
|
+
).sort().join("|");
|
|
8645
|
+
};
|
|
8646
|
+
function factorial(n) {
|
|
8647
|
+
if (!Number.isInteger(n) || n < 0) {
|
|
8648
|
+
throw new RangeError("n must be a non-negative integer");
|
|
8649
|
+
}
|
|
8650
|
+
let result = 1;
|
|
8651
|
+
for (let i = 2; i <= n; i++) {
|
|
8652
|
+
result *= i;
|
|
8653
|
+
}
|
|
8654
|
+
return result;
|
|
8655
|
+
}
|
|
8656
|
+
var MultiHeadPolyLineIntraNodeSolver3 = class extends MultiHeadPolyLineIntraNodeSolver2 {
|
|
8657
|
+
constructor(params) {
|
|
8658
|
+
super(params);
|
|
8659
|
+
this.MAX_ITERATIONS = 1e3;
|
|
8660
|
+
}
|
|
8661
|
+
createInitialCandidateFromSeed(shuffleSeed) {
|
|
8662
|
+
const viaSolver = new ViaPossibilitiesSolver2({
|
|
8663
|
+
nodeWithPortPoints: this.nodeWithPortPoints,
|
|
8664
|
+
colorMap: this.colorMap,
|
|
8665
|
+
// Pass relevant hyperparameters if needed, e.g., shuffle seed
|
|
8666
|
+
hyperParameters: {
|
|
8667
|
+
SHUFFLE_SEED: shuffleSeed
|
|
8668
|
+
}
|
|
8669
|
+
});
|
|
8670
|
+
viaSolver.solve();
|
|
8671
|
+
if (viaSolver.failed || !viaSolver.solved) {
|
|
8672
|
+
this.failed = true;
|
|
8673
|
+
this.error = viaSolver.error ?? "ViaPossibilitiesSolver2 failed to find a solution.";
|
|
8674
|
+
console.error(this.error);
|
|
8675
|
+
return null;
|
|
8676
|
+
}
|
|
8677
|
+
const polyLines = [];
|
|
8678
|
+
let totalViaCount = 0;
|
|
8679
|
+
for (const [
|
|
8680
|
+
connectionName,
|
|
8681
|
+
pathPoints
|
|
8682
|
+
] of viaSolver.completedPaths.entries()) {
|
|
8683
|
+
if (pathPoints.length < 2) {
|
|
8684
|
+
console.warn(
|
|
8685
|
+
`Skipping connection "${connectionName}" due to insufficient points (${pathPoints.length}) in ViaPossibilitiesSolver2 path.`
|
|
8686
|
+
);
|
|
8687
|
+
continue;
|
|
8688
|
+
}
|
|
8689
|
+
const startPoint = pathPoints[0];
|
|
8690
|
+
const endPoint = pathPoints[pathPoints.length - 1];
|
|
8691
|
+
const middlePointsRaw = pathPoints.slice(1, -1);
|
|
8692
|
+
const mPoints = [];
|
|
8693
|
+
let currentViaCount = 0;
|
|
8694
|
+
let lastZ = startPoint.z;
|
|
8695
|
+
for (let i = 0; i < middlePointsRaw.length; i++) {
|
|
8696
|
+
const currentRawPoint = middlePointsRaw[i];
|
|
8697
|
+
const nextRawPoint = i + 1 < middlePointsRaw.length ? middlePointsRaw[i + 1] : endPoint;
|
|
8698
|
+
const isViaStart = i + 1 < middlePointsRaw.length && currentRawPoint.x === nextRawPoint.x && currentRawPoint.y === nextRawPoint.y && currentRawPoint.z !== nextRawPoint.z;
|
|
8699
|
+
const z1 = lastZ;
|
|
8700
|
+
const z2 = isViaStart ? nextRawPoint.z : currentRawPoint.z;
|
|
8701
|
+
mPoints.push({
|
|
8702
|
+
x: currentRawPoint.x,
|
|
8703
|
+
y: currentRawPoint.y,
|
|
8704
|
+
z1,
|
|
8705
|
+
z2
|
|
8706
|
+
});
|
|
8707
|
+
if (z1 !== z2) {
|
|
8708
|
+
currentViaCount++;
|
|
8709
|
+
i++;
|
|
8710
|
+
lastZ = z2;
|
|
8711
|
+
} else {
|
|
8712
|
+
lastZ = currentRawPoint.z;
|
|
8713
|
+
}
|
|
8714
|
+
}
|
|
8715
|
+
totalViaCount += currentViaCount;
|
|
8716
|
+
const targetSegmentCount = this.SEGMENTS_PER_POLYLINE;
|
|
8717
|
+
let currentSegments = mPoints.length + 1;
|
|
8718
|
+
while (currentSegments < targetSegmentCount) {
|
|
8719
|
+
let longestSegmentLength = -1;
|
|
8720
|
+
let longestSegmentIndex = -1;
|
|
8721
|
+
let p1 = null;
|
|
8722
|
+
let p2 = null;
|
|
8723
|
+
const fullPathPoints = [
|
|
8724
|
+
{
|
|
8725
|
+
...startPoint,
|
|
8726
|
+
z1: startPoint.z,
|
|
8727
|
+
z2: startPoint.z,
|
|
8728
|
+
connectionName
|
|
8729
|
+
},
|
|
8730
|
+
...mPoints,
|
|
8731
|
+
{ ...endPoint, z1: endPoint.z, z2: endPoint.z, connectionName }
|
|
8732
|
+
];
|
|
8733
|
+
for (let k = 0; k < fullPathPoints.length - 1; k++) {
|
|
8734
|
+
const segP1 = fullPathPoints[k];
|
|
8735
|
+
const segP2 = fullPathPoints[k + 1];
|
|
8736
|
+
if (segP1.x === segP2.x && segP1.y === segP2.y) {
|
|
8737
|
+
continue;
|
|
8738
|
+
}
|
|
8739
|
+
const len = distance(segP1, segP2);
|
|
8740
|
+
if (len > longestSegmentLength) {
|
|
8741
|
+
longestSegmentLength = len;
|
|
8742
|
+
longestSegmentIndex = k;
|
|
8743
|
+
p1 = segP1;
|
|
8744
|
+
p2 = segP2;
|
|
8745
|
+
}
|
|
8746
|
+
}
|
|
8747
|
+
if (longestSegmentIndex === -1 || !p1 || !p2) {
|
|
8748
|
+
console.warn(
|
|
8749
|
+
`Could not find longest segment for ${connectionName} while trying to reach ${targetSegmentCount} segments.`
|
|
8750
|
+
);
|
|
8751
|
+
break;
|
|
8752
|
+
}
|
|
8753
|
+
const midX = (p1.x + p2.x) / 2;
|
|
8754
|
+
const midY = (p1.y + p2.y) / 2;
|
|
8755
|
+
const segmentZ = p1.z2;
|
|
8756
|
+
const newMPoint = {
|
|
8757
|
+
x: midX,
|
|
8758
|
+
y: midY,
|
|
8759
|
+
z1: segmentZ,
|
|
8760
|
+
// New point is on the same layer
|
|
8761
|
+
z2: segmentZ
|
|
8762
|
+
};
|
|
8763
|
+
mPoints.splice(longestSegmentIndex, 0, newMPoint);
|
|
8764
|
+
currentSegments++;
|
|
8765
|
+
}
|
|
8766
|
+
polyLines.push({
|
|
8767
|
+
connectionName,
|
|
8768
|
+
start: {
|
|
8769
|
+
// Use original start/end points from ViaSolver
|
|
8770
|
+
...startPoint,
|
|
8771
|
+
z1: startPoint.z,
|
|
8772
|
+
z2: startPoint.z
|
|
8773
|
+
// Start point is not a via itself
|
|
8774
|
+
},
|
|
8775
|
+
end: {
|
|
8776
|
+
...endPoint,
|
|
8777
|
+
z1: endPoint.z,
|
|
8778
|
+
// End point uses its own Z as z1
|
|
8779
|
+
z2: endPoint.z
|
|
8780
|
+
// End point is not a via itself
|
|
8781
|
+
},
|
|
8782
|
+
mPoints
|
|
8783
|
+
});
|
|
8784
|
+
}
|
|
8785
|
+
if (polyLines.length === 0) {
|
|
8786
|
+
this.failed = true;
|
|
8787
|
+
this.error = "No valid polylines generated from ViaPossibilitiesSolver2.";
|
|
8788
|
+
console.error(this.error);
|
|
8789
|
+
return null;
|
|
8790
|
+
}
|
|
8791
|
+
const minGaps = this.computeMinGapBtwPolyLines(polyLines);
|
|
8792
|
+
const h = this.computeH({ minGaps, forces: [] });
|
|
8793
|
+
const initialCandidate = {
|
|
8794
|
+
polyLines,
|
|
8795
|
+
g: 0,
|
|
8796
|
+
h,
|
|
8797
|
+
f: 0 + h,
|
|
8798
|
+
// f = g + h
|
|
8799
|
+
viaCount: totalViaCount,
|
|
8800
|
+
minGaps
|
|
8801
|
+
};
|
|
8802
|
+
initialCandidate.g = this.computeG(polyLines, initialCandidate);
|
|
8803
|
+
initialCandidate.f = initialCandidate.g + initialCandidate.h;
|
|
8804
|
+
return initialCandidate;
|
|
8805
|
+
}
|
|
8806
|
+
setupInitialPolyLines() {
|
|
8807
|
+
this.candidates = [];
|
|
8808
|
+
const maxCandidatesToGenerate = Math.min(
|
|
8809
|
+
2e3,
|
|
8810
|
+
factorial(this.uniqueConnections)
|
|
8811
|
+
);
|
|
8812
|
+
const candidatePolylineHashes = /* @__PURE__ */ new Set();
|
|
8813
|
+
for (let i = 0; i < maxCandidatesToGenerate; i++) {
|
|
8814
|
+
const newCandidate = this.createInitialCandidateFromSeed(i);
|
|
8815
|
+
if (!newCandidate) continue;
|
|
8816
|
+
const newCandidatePolylineHash = hashPolyLines(newCandidate.polyLines);
|
|
8817
|
+
if (candidatePolylineHashes.has(newCandidatePolylineHash)) continue;
|
|
8818
|
+
candidatePolylineHashes.add(newCandidatePolylineHash);
|
|
8819
|
+
this.candidates.push(newCandidate);
|
|
8820
|
+
}
|
|
8821
|
+
this.candidates.sort((a, b) => a.f - b.f);
|
|
8822
|
+
}
|
|
8823
|
+
};
|
|
8824
|
+
|
|
8262
8825
|
// lib/solvers/HyperHighDensitySolver/HyperSingleIntraNodeSolver.ts
|
|
8263
8826
|
var HyperSingleIntraNodeSolver = class extends HyperParameterSupervisorSolver {
|
|
8264
8827
|
constructorParams;
|
|
@@ -8381,11 +8944,7 @@ var HyperSingleIntraNodeSolver = class extends HyperParameterSupervisorSolver {
|
|
|
8381
8944
|
possibleValues: [
|
|
8382
8945
|
{
|
|
8383
8946
|
MULTI_HEAD_POLYLINE_SOLVER: true,
|
|
8384
|
-
SEGMENTS_PER_POLYLINE:
|
|
8385
|
-
},
|
|
8386
|
-
{
|
|
8387
|
-
MULTI_HEAD_POLYLINE_SOLVER: true,
|
|
8388
|
-
SEGMENTS_PER_POLYLINE: 4
|
|
8947
|
+
SEGMENTS_PER_POLYLINE: 6
|
|
8389
8948
|
}
|
|
8390
8949
|
]
|
|
8391
8950
|
}
|
|
@@ -8412,7 +8971,7 @@ var HyperSingleIntraNodeSolver = class extends HyperParameterSupervisorSolver {
|
|
|
8412
8971
|
});
|
|
8413
8972
|
}
|
|
8414
8973
|
if (hyperParameters.MULTI_HEAD_POLYLINE_SOLVER) {
|
|
8415
|
-
return new
|
|
8974
|
+
return new MultiHeadPolyLineIntraNodeSolver3({
|
|
8416
8975
|
nodeWithPortPoints: this.nodeWithPortPoints,
|
|
8417
8976
|
hyperParameters
|
|
8418
8977
|
});
|
|
@@ -8502,7 +9061,7 @@ var HighDensitySolver = class extends BaseSolver {
|
|
|
8502
9061
|
if (this.failedSolvers.length > 0) {
|
|
8503
9062
|
this.solved = false;
|
|
8504
9063
|
this.failed = true;
|
|
8505
|
-
this.error = `Failed to solve ${this.failedSolvers.length} nodes`;
|
|
9064
|
+
this.error = `Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0, 5).map((fs) => fs.nodeWithPortPoints.capacityMeshNodeId)}`;
|
|
8506
9065
|
return;
|
|
8507
9066
|
}
|
|
8508
9067
|
this.solved = true;
|
|
@@ -8533,6 +9092,7 @@ var HighDensitySolver = class extends BaseSolver {
|
|
|
8533
9092
|
points: segment.points,
|
|
8534
9093
|
label: segment.connectionName,
|
|
8535
9094
|
strokeColor: segment.z === 0 ? segment.color : safeTransparentize(segment.color, 0.75),
|
|
9095
|
+
layer: `z${segment.z}`,
|
|
8536
9096
|
strokeWidth: route.traceThickness,
|
|
8537
9097
|
strokeDash: segment.z !== 0 ? "10, 5" : void 0
|
|
8538
9098
|
});
|
|
@@ -8540,6 +9100,7 @@ var HighDensitySolver = class extends BaseSolver {
|
|
|
8540
9100
|
for (const via of route.vias) {
|
|
8541
9101
|
graphics.circles.push({
|
|
8542
9102
|
center: via,
|
|
9103
|
+
layer: "z0,1",
|
|
8543
9104
|
radius: route.viaDiameter / 2,
|
|
8544
9105
|
fill: this.colorMap[route.connectionName],
|
|
8545
9106
|
label: `${route.connectionName} via`
|
|
@@ -8555,6 +9116,7 @@ var HighDensitySolver = class extends BaseSolver {
|
|
|
8555
9116
|
x: node.center.x - rectWidth / 2,
|
|
8556
9117
|
y: node.center.y - rectHeight / 2
|
|
8557
9118
|
},
|
|
9119
|
+
layer: "did_not_connect",
|
|
8558
9120
|
width: rectWidth,
|
|
8559
9121
|
height: rectHeight,
|
|
8560
9122
|
fill: "red",
|
|
@@ -8574,7 +9136,8 @@ var HighDensitySolver = class extends BaseSolver {
|
|
|
8574
9136
|
graphics.lines.push({
|
|
8575
9137
|
points: [start, end],
|
|
8576
9138
|
strokeColor: "red",
|
|
8577
|
-
strokeDash: "10, 5"
|
|
9139
|
+
strokeDash: "10, 5",
|
|
9140
|
+
layer: "did_not_connect"
|
|
8578
9141
|
});
|
|
8579
9142
|
}
|
|
8580
9143
|
}
|
|
@@ -11476,7 +12039,7 @@ ${percent}% (Pf: ${(probabilityOfFailure * 100).toFixed(1)}%)`;
|
|
|
11476
12039
|
}
|
|
11477
12040
|
|
|
11478
12041
|
// lib/solvers/CapacityPathingSectionSolver/CapacityPathingSingleSectionPathingSolver.ts
|
|
11479
|
-
var
|
|
12042
|
+
var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
11480
12043
|
GREEDY_MULTIPLIER = 1.5;
|
|
11481
12044
|
sectionNodes;
|
|
11482
12045
|
sectionEdges;
|
|
@@ -11488,6 +12051,7 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
|
|
|
11488
12051
|
colorMap;
|
|
11489
12052
|
usedNodeCapacityMap;
|
|
11490
12053
|
// Tracks capacity usage *within this solver's run*
|
|
12054
|
+
centerNodeId;
|
|
11491
12055
|
MAX_CANDIDATES_IN_MEMORY = 1e4;
|
|
11492
12056
|
// A* state
|
|
11493
12057
|
currentConnectionIndex = 0;
|
|
@@ -11501,6 +12065,7 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
|
|
|
11501
12065
|
// Default, similar to CapacityPathingSolver5
|
|
11502
12066
|
constructor(params) {
|
|
11503
12067
|
super();
|
|
12068
|
+
this.centerNodeId = params.centerNodeId;
|
|
11504
12069
|
this.sectionNodes = params.sectionNodes;
|
|
11505
12070
|
this.sectionEdges = params.sectionEdges;
|
|
11506
12071
|
this.sectionConnectionTerminals = params.sectionConnectionTerminals.map(
|
|
@@ -11674,6 +12239,28 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
|
|
|
11674
12239
|
candidates.push(newCandidate);
|
|
11675
12240
|
}
|
|
11676
12241
|
}
|
|
12242
|
+
computeProgress() {
|
|
12243
|
+
const totalConnections = this.sectionConnectionTerminals.length;
|
|
12244
|
+
if (totalConnections === 0) return 1;
|
|
12245
|
+
const completedConnections = this.currentConnectionIndex;
|
|
12246
|
+
let progress = completedConnections / totalConnections;
|
|
12247
|
+
if (this.currentConnectionIndex < totalConnections && this.candidates && this.candidates.length > 0 && this.activeCandidateStraightLineDistance && this.activeCandidateStraightLineDistance > 0) {
|
|
12248
|
+
const bestCandidate = this.candidates.reduce(
|
|
12249
|
+
(best, current) => current.f < best.f ? current : best
|
|
12250
|
+
);
|
|
12251
|
+
const currentConnectionProgress = Math.max(
|
|
12252
|
+
0,
|
|
12253
|
+
Math.min(
|
|
12254
|
+
1,
|
|
12255
|
+
1 - bestCandidate.h / this.activeCandidateStraightLineDistance
|
|
12256
|
+
)
|
|
12257
|
+
);
|
|
12258
|
+
progress += currentConnectionProgress / totalConnections;
|
|
12259
|
+
} else if (this.solved) {
|
|
12260
|
+
progress = 1;
|
|
12261
|
+
}
|
|
12262
|
+
return Math.min(1, progress);
|
|
12263
|
+
}
|
|
11677
12264
|
_setupAStar(startNode, endNode) {
|
|
11678
12265
|
this.candidates = [
|
|
11679
12266
|
{ prevCandidate: null, node: startNode, f: 0, g: 0, h: 0 }
|
|
@@ -11778,133 +12365,157 @@ var CapacityPathingSingleSectionPathingSolver = class extends BaseSolver {
|
|
|
11778
12365
|
return baseGraphics;
|
|
11779
12366
|
}
|
|
11780
12367
|
};
|
|
12368
|
+
var CapacityPathingSingleSectionPathingSolver = CapacityPathingSingleSectionSolver;
|
|
11781
12369
|
|
|
11782
|
-
// lib/solvers/CapacityPathingSectionSolver/
|
|
11783
|
-
var
|
|
11784
|
-
|
|
11785
|
-
|
|
11786
|
-
nodes;
|
|
11787
|
-
nodeMap;
|
|
11788
|
-
edges;
|
|
11789
|
-
nodeEdgeMap;
|
|
11790
|
-
expansionDegrees;
|
|
11791
|
-
colorMap;
|
|
11792
|
-
sectionNodes;
|
|
11793
|
-
sectionEdges;
|
|
11794
|
-
// Added sectionEdges property
|
|
11795
|
-
sectionConnectionTerminals;
|
|
11796
|
-
activeSubSolver = null;
|
|
12370
|
+
// lib/solvers/CapacityPathingSectionSolver/HyperCapacityPathingSingleSectionSolver.ts
|
|
12371
|
+
var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSupervisorSolver {
|
|
12372
|
+
constructorParams;
|
|
12373
|
+
winningSolver;
|
|
11797
12374
|
constructor(params) {
|
|
11798
12375
|
super();
|
|
11799
|
-
this.MAX_ITERATIONS =
|
|
11800
|
-
this.
|
|
11801
|
-
this.centerNodeId = params.centerNodeId;
|
|
11802
|
-
this.connectionsWithNodes = params.connectionsWithNodes;
|
|
11803
|
-
this.nodes = params.nodes;
|
|
11804
|
-
this.nodeMap = new Map(this.nodes.map((n) => [n.capacityMeshNodeId, n]));
|
|
11805
|
-
this.edges = params.edges;
|
|
11806
|
-
this.nodeEdgeMap = getNodeEdgeMap(this.edges);
|
|
11807
|
-
this.expansionDegrees = params.hyperParameters?.EXPANSION_DEGREES ?? 3;
|
|
11808
|
-
this.sectionNodes = [];
|
|
11809
|
-
this.sectionEdges = [];
|
|
11810
|
-
this.sectionConnectionTerminals = [];
|
|
11811
|
-
this.computeSectionNodesTerminalsAndEdges();
|
|
11812
|
-
this.activeSubSolver = new CapacityPathingSingleSectionPathingSolver({
|
|
11813
|
-
sectionConnectionTerminals: this.sectionConnectionTerminals,
|
|
11814
|
-
sectionNodes: this.sectionNodes,
|
|
11815
|
-
sectionEdges: this.sectionEdges,
|
|
11816
|
-
colorMap: this.colorMap,
|
|
11817
|
-
hyperParameters: params.hyperParameters
|
|
11818
|
-
});
|
|
12376
|
+
this.MAX_ITERATIONS = 1e4;
|
|
12377
|
+
this.constructorParams = params;
|
|
11819
12378
|
}
|
|
11820
|
-
|
|
11821
|
-
|
|
11822
|
-
const queue = [
|
|
11823
|
-
{ nodeId: this.centerNodeId, depth: 0 }
|
|
11824
|
-
];
|
|
11825
|
-
sectionNodeIds.add(this.centerNodeId);
|
|
11826
|
-
let head = 0;
|
|
11827
|
-
while (head < queue.length) {
|
|
11828
|
-
const { nodeId, depth } = queue[head++];
|
|
11829
|
-
if (depth >= this.expansionDegrees) continue;
|
|
11830
|
-
const neighbors = this.nodeEdgeMap.get(nodeId)?.flatMap((edge) => edge.nodeIds.filter((id) => id !== nodeId)) ?? [];
|
|
11831
|
-
for (const neighborId of neighbors) {
|
|
11832
|
-
if (!sectionNodeIds.has(neighborId)) {
|
|
11833
|
-
sectionNodeIds.add(neighborId);
|
|
11834
|
-
queue.push({ nodeId: neighborId, depth: depth + 1 });
|
|
11835
|
-
}
|
|
11836
|
-
}
|
|
11837
|
-
}
|
|
11838
|
-
this.sectionNodes = Array.from(sectionNodeIds).map(
|
|
11839
|
-
(id) => this.nodeMap.get(id)
|
|
11840
|
-
);
|
|
11841
|
-
this.sectionEdges = this.edges.filter((edge) => {
|
|
11842
|
-
const [nodeIdA, nodeIdB] = edge.nodeIds;
|
|
11843
|
-
return sectionNodeIds.has(nodeIdA) && sectionNodeIds.has(nodeIdB);
|
|
11844
|
-
});
|
|
11845
|
-
this.sectionConnectionTerminals = [];
|
|
11846
|
-
for (const conn of this.connectionsWithNodes) {
|
|
11847
|
-
if (!conn.path) continue;
|
|
11848
|
-
let startNodeId = null;
|
|
11849
|
-
let endNodeId = null;
|
|
11850
|
-
for (const node of conn.path) {
|
|
11851
|
-
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
11852
|
-
startNodeId = node.capacityMeshNodeId;
|
|
11853
|
-
break;
|
|
11854
|
-
}
|
|
11855
|
-
}
|
|
11856
|
-
for (let i = conn.path.length - 1; i >= 0; i--) {
|
|
11857
|
-
const node = conn.path[i];
|
|
11858
|
-
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
11859
|
-
endNodeId = node.capacityMeshNodeId;
|
|
11860
|
-
break;
|
|
11861
|
-
}
|
|
11862
|
-
}
|
|
11863
|
-
if (startNodeId && endNodeId) {
|
|
11864
|
-
this.sectionConnectionTerminals.push({
|
|
11865
|
-
connectionName: conn.connection.name,
|
|
11866
|
-
startNodeId,
|
|
11867
|
-
endNodeId
|
|
11868
|
-
});
|
|
11869
|
-
}
|
|
11870
|
-
}
|
|
12379
|
+
computeG(solver) {
|
|
12380
|
+
return solver.iterations / 100;
|
|
11871
12381
|
}
|
|
11872
|
-
|
|
11873
|
-
|
|
11874
|
-
if (this.activeSubSolver?.solved) {
|
|
11875
|
-
this.solved = true;
|
|
11876
|
-
return;
|
|
11877
|
-
}
|
|
11878
|
-
if (this.activeSubSolver?.failed) {
|
|
11879
|
-
this.failed = true;
|
|
11880
|
-
this.error = this.activeSubSolver.error;
|
|
11881
|
-
return;
|
|
11882
|
-
}
|
|
12382
|
+
computeH(solver) {
|
|
12383
|
+
return solver.computeProgress();
|
|
11883
12384
|
}
|
|
11884
|
-
|
|
12385
|
+
getCombinationDefs() {
|
|
12386
|
+
return [["orderings10"]];
|
|
12387
|
+
}
|
|
12388
|
+
getFailureMessage() {
|
|
12389
|
+
return `All CapacityPathingSingleSection solvers failed for "${this.centerNodeId}"`;
|
|
12390
|
+
}
|
|
12391
|
+
getHyperParameterDefs() {
|
|
11885
12392
|
return [
|
|
11886
12393
|
{
|
|
11887
|
-
|
|
11888
|
-
|
|
11889
|
-
|
|
11890
|
-
|
|
11891
|
-
|
|
12394
|
+
name: "orderings10",
|
|
12395
|
+
possibleValues: [
|
|
12396
|
+
{
|
|
12397
|
+
SHUFFLE_SEED: 0
|
|
12398
|
+
},
|
|
12399
|
+
{
|
|
12400
|
+
SHUFFLE_SEED: 1
|
|
12401
|
+
},
|
|
12402
|
+
{
|
|
12403
|
+
SHUFFLE_SEED: 2
|
|
12404
|
+
},
|
|
12405
|
+
{
|
|
12406
|
+
SHUFFLE_SEED: 3
|
|
12407
|
+
},
|
|
12408
|
+
{
|
|
12409
|
+
SHUFFLE_SEED: 4
|
|
12410
|
+
},
|
|
12411
|
+
{
|
|
12412
|
+
SHUFFLE_SEED: 5
|
|
12413
|
+
},
|
|
12414
|
+
{
|
|
12415
|
+
SHUFFLE_SEED: 6
|
|
12416
|
+
},
|
|
12417
|
+
{
|
|
12418
|
+
SHUFFLE_SEED: 7
|
|
12419
|
+
},
|
|
12420
|
+
{
|
|
12421
|
+
SHUFFLE_SEED: 8
|
|
12422
|
+
},
|
|
12423
|
+
{
|
|
12424
|
+
SHUFFLE_SEED: 9
|
|
12425
|
+
}
|
|
12426
|
+
]
|
|
11892
12427
|
}
|
|
11893
12428
|
];
|
|
11894
12429
|
}
|
|
11895
|
-
|
|
11896
|
-
return
|
|
11897
|
-
|
|
11898
|
-
|
|
11899
|
-
|
|
11900
|
-
|
|
11901
|
-
|
|
11902
|
-
colorMap: this.colorMap,
|
|
11903
|
-
centerNodeId: this.centerNodeId,
|
|
11904
|
-
nodeOpacity: 1e-3,
|
|
11905
|
-
title: `Section Solver (Center: ${this.centerNodeId}, Hops: ${this.expansionDegrees})`
|
|
12430
|
+
generateSolver(hyperParameters) {
|
|
12431
|
+
return new CapacityPathingSingleSectionPathingSolver({
|
|
12432
|
+
...this.constructorParams,
|
|
12433
|
+
hyperParameters: {
|
|
12434
|
+
...this.constructorParams.hyperParameters,
|
|
12435
|
+
...hyperParameters
|
|
12436
|
+
}
|
|
11906
12437
|
});
|
|
11907
12438
|
}
|
|
12439
|
+
onSolve({
|
|
12440
|
+
solver
|
|
12441
|
+
}) {
|
|
12442
|
+
this.winningSolver = solver;
|
|
12443
|
+
}
|
|
12444
|
+
get centerNodeId() {
|
|
12445
|
+
return this.constructorParams.centerNodeId;
|
|
12446
|
+
}
|
|
12447
|
+
get sectionNodes() {
|
|
12448
|
+
return this.constructorParams.sectionNodes;
|
|
12449
|
+
}
|
|
12450
|
+
get sectionConnectionTerminals() {
|
|
12451
|
+
return this.winningSolver?.sectionConnectionTerminals;
|
|
12452
|
+
}
|
|
12453
|
+
};
|
|
12454
|
+
|
|
12455
|
+
// lib/solvers/CapacityPathingSectionSolver/computeSectionNodesTerminalsAndEdges.ts
|
|
12456
|
+
var computeSectionNodesTerminalsAndEdges = (opts) => {
|
|
12457
|
+
const {
|
|
12458
|
+
centerNodeId,
|
|
12459
|
+
connectionsWithNodes,
|
|
12460
|
+
nodeMap,
|
|
12461
|
+
edges,
|
|
12462
|
+
nodeEdgeMap,
|
|
12463
|
+
expansionDegrees
|
|
12464
|
+
} = opts;
|
|
12465
|
+
const sectionNodeIds = /* @__PURE__ */ new Set();
|
|
12466
|
+
const queue = [
|
|
12467
|
+
{ nodeId: centerNodeId, depth: 0 }
|
|
12468
|
+
];
|
|
12469
|
+
sectionNodeIds.add(centerNodeId);
|
|
12470
|
+
let head = 0;
|
|
12471
|
+
while (head < queue.length) {
|
|
12472
|
+
const { nodeId, depth } = queue[head++];
|
|
12473
|
+
if (depth >= expansionDegrees) continue;
|
|
12474
|
+
const neighbors = nodeEdgeMap.get(nodeId)?.flatMap((edge) => edge.nodeIds.filter((id) => id !== nodeId)) ?? [];
|
|
12475
|
+
for (const neighborId of neighbors) {
|
|
12476
|
+
if (!sectionNodeIds.has(neighborId)) {
|
|
12477
|
+
sectionNodeIds.add(neighborId);
|
|
12478
|
+
queue.push({ nodeId: neighborId, depth: depth + 1 });
|
|
12479
|
+
}
|
|
12480
|
+
}
|
|
12481
|
+
}
|
|
12482
|
+
const sectionNodes = Array.from(sectionNodeIds).map((id) => nodeMap.get(id));
|
|
12483
|
+
const sectionEdges = edges.filter((edge) => {
|
|
12484
|
+
const [nodeIdA, nodeIdB] = edge.nodeIds;
|
|
12485
|
+
return sectionNodeIds.has(nodeIdA) && sectionNodeIds.has(nodeIdB);
|
|
12486
|
+
});
|
|
12487
|
+
const sectionConnectionTerminals = [];
|
|
12488
|
+
for (const conn of connectionsWithNodes) {
|
|
12489
|
+
if (!conn.path) continue;
|
|
12490
|
+
let startNodeId = null;
|
|
12491
|
+
let endNodeId = null;
|
|
12492
|
+
for (const node of conn.path) {
|
|
12493
|
+
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
12494
|
+
startNodeId = node.capacityMeshNodeId;
|
|
12495
|
+
break;
|
|
12496
|
+
}
|
|
12497
|
+
}
|
|
12498
|
+
for (let i = conn.path.length - 1; i >= 0; i--) {
|
|
12499
|
+
const node = conn.path[i];
|
|
12500
|
+
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
12501
|
+
endNodeId = node.capacityMeshNodeId;
|
|
12502
|
+
break;
|
|
12503
|
+
}
|
|
12504
|
+
}
|
|
12505
|
+
if (startNodeId && endNodeId) {
|
|
12506
|
+
sectionConnectionTerminals.push({
|
|
12507
|
+
connectionName: conn.connection.name,
|
|
12508
|
+
startNodeId,
|
|
12509
|
+
endNodeId
|
|
12510
|
+
});
|
|
12511
|
+
}
|
|
12512
|
+
}
|
|
12513
|
+
return {
|
|
12514
|
+
sectionConnectionTerminals,
|
|
12515
|
+
sectionNodes,
|
|
12516
|
+
sectionEdges,
|
|
12517
|
+
centerNodeId
|
|
12518
|
+
};
|
|
11908
12519
|
};
|
|
11909
12520
|
|
|
11910
12521
|
// lib/solvers/CapacityPathingSectionSolver/CapacityPathingMultiSectionSolver.ts
|
|
@@ -11912,6 +12523,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
11912
12523
|
simpleRouteJson;
|
|
11913
12524
|
nodes;
|
|
11914
12525
|
edges;
|
|
12526
|
+
nodeEdgeMap;
|
|
11915
12527
|
connectionsWithNodes = [];
|
|
11916
12528
|
// Initialize here
|
|
11917
12529
|
colorMap;
|
|
@@ -11923,12 +12535,18 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
11923
12535
|
// Added
|
|
11924
12536
|
nodeCapacityPercentMap = /* @__PURE__ */ new Map();
|
|
11925
12537
|
nodeOptimizationAttemptCountMap = /* @__PURE__ */ new Map();
|
|
12538
|
+
currentSection = null;
|
|
11926
12539
|
sectionSolver = null;
|
|
11927
|
-
MAX_ATTEMPTS_PER_NODE =
|
|
12540
|
+
MAX_ATTEMPTS_PER_NODE = 1;
|
|
11928
12541
|
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE = 0.05;
|
|
11929
|
-
MAX_EXPANSION_DEGREES =
|
|
12542
|
+
MAX_EXPANSION_DEGREES = 5;
|
|
12543
|
+
stats;
|
|
11930
12544
|
constructor(params) {
|
|
11931
12545
|
super();
|
|
12546
|
+
this.stats = {
|
|
12547
|
+
successfulOptimizations: 0,
|
|
12548
|
+
failedOptimizations: 0
|
|
12549
|
+
};
|
|
11932
12550
|
this.MAX_ITERATIONS = 1e7;
|
|
11933
12551
|
this.simpleRouteJson = params.simpleRouteJson;
|
|
11934
12552
|
this.nodes = params.nodes;
|
|
@@ -11937,7 +12555,8 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
11937
12555
|
this.nodeMap = new Map(
|
|
11938
12556
|
this.nodes.map((node) => [node.capacityMeshNodeId, node])
|
|
11939
12557
|
);
|
|
11940
|
-
this.
|
|
12558
|
+
this.nodeEdgeMap = getNodeEdgeMap(this.edges);
|
|
12559
|
+
this.initialSolver = params.initialPathingSolver || new CapacityPathingGreedySolver({
|
|
11941
12560
|
simpleRouteJson: this.simpleRouteJson,
|
|
11942
12561
|
nodes: this.nodes,
|
|
11943
12562
|
edges: this.edges,
|
|
@@ -12002,16 +12621,21 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
12002
12621
|
this.solved = true;
|
|
12003
12622
|
return;
|
|
12004
12623
|
}
|
|
12005
|
-
|
|
12624
|
+
const section = computeSectionNodesTerminalsAndEdges({
|
|
12006
12625
|
centerNodeId,
|
|
12007
12626
|
connectionsWithNodes: this.connectionsWithNodes,
|
|
12008
|
-
|
|
12627
|
+
nodeMap: this.nodeMap,
|
|
12009
12628
|
edges: this.edges,
|
|
12629
|
+
expansionDegrees: this.MAX_EXPANSION_DEGREES,
|
|
12630
|
+
nodeEdgeMap: this.nodeEdgeMap
|
|
12631
|
+
});
|
|
12632
|
+
this.currentSection = section;
|
|
12633
|
+
this.sectionSolver = new HyperCapacityPathingSingleSectionSolver({
|
|
12634
|
+
sectionConnectionTerminals: section.sectionConnectionTerminals,
|
|
12635
|
+
sectionEdges: section.sectionEdges,
|
|
12636
|
+
sectionNodes: section.sectionNodes,
|
|
12010
12637
|
colorMap: this.colorMap,
|
|
12011
|
-
|
|
12012
|
-
EXPANSION_DEGREES: this.MAX_EXPANSION_DEGREES,
|
|
12013
|
-
SHUFFLE_SEED: this.iterations
|
|
12014
|
-
}
|
|
12638
|
+
centerNodeId: section.centerNodeId
|
|
12015
12639
|
});
|
|
12016
12640
|
this.activeSubSolver = this.sectionSolver;
|
|
12017
12641
|
this.nodeOptimizationAttemptCountMap.set(
|
|
@@ -12022,7 +12646,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
12022
12646
|
this.sectionSolver.step();
|
|
12023
12647
|
if (this.sectionSolver.failed) {
|
|
12024
12648
|
console.warn(
|
|
12025
|
-
`Section solver failed for node ${this.
|
|
12649
|
+
`Section solver failed for node ${this.currentSection.centerNodeId}. Error: ${this.sectionSolver.error}`
|
|
12026
12650
|
);
|
|
12027
12651
|
this.sectionSolver = null;
|
|
12028
12652
|
this.activeSubSolver = null;
|
|
@@ -12030,12 +12654,12 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
12030
12654
|
}
|
|
12031
12655
|
if (this.sectionSolver.solved) {
|
|
12032
12656
|
const solvedSectionSolver = this.sectionSolver;
|
|
12033
|
-
const pathingSolver = solvedSectionSolver
|
|
12657
|
+
const pathingSolver = solvedSectionSolver?.activeSubSolver || solvedSectionSolver;
|
|
12034
12658
|
this.sectionSolver = null;
|
|
12035
12659
|
this.activeSubSolver = null;
|
|
12036
12660
|
if (!pathingSolver || !pathingSolver.solved) {
|
|
12037
12661
|
console.warn(
|
|
12038
|
-
`Pathing sub-solver for section ${
|
|
12662
|
+
`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`
|
|
12039
12663
|
);
|
|
12040
12664
|
return;
|
|
12041
12665
|
}
|
|
@@ -12085,9 +12709,11 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
12085
12709
|
sectionNodeIds
|
|
12086
12710
|
});
|
|
12087
12711
|
if (afterScore > beforeScore) {
|
|
12712
|
+
this.stats.successfulOptimizations++;
|
|
12088
12713
|
this._mergeSolvedSectionPaths(solvedSectionSolver);
|
|
12089
12714
|
this._recalculateNodeCapacityUsage();
|
|
12090
12715
|
} else {
|
|
12716
|
+
this.stats.failedOptimizations++;
|
|
12091
12717
|
}
|
|
12092
12718
|
}
|
|
12093
12719
|
}
|
|
@@ -12096,18 +12722,18 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
12096
12722
|
* connectionsWithNodes list.
|
|
12097
12723
|
*/
|
|
12098
12724
|
_mergeSolvedSectionPaths(solvedSectionSolver) {
|
|
12099
|
-
const
|
|
12100
|
-
if (!
|
|
12725
|
+
const centerNodeId = solvedSectionSolver.centerNodeId;
|
|
12726
|
+
if (!solvedSectionSolver || !solvedSectionSolver.solved) {
|
|
12101
12727
|
console.warn(
|
|
12102
|
-
`Pathing sub-solver for section ${
|
|
12728
|
+
`Pathing sub-solver for section ${centerNodeId} did not complete successfully. Skipping merge.`
|
|
12103
12729
|
);
|
|
12104
12730
|
return;
|
|
12105
12731
|
}
|
|
12106
|
-
const solvedTerminals =
|
|
12732
|
+
const solvedTerminals = solvedSectionSolver.sectionConnectionTerminals;
|
|
12107
12733
|
for (const solvedTerminal of solvedTerminals) {
|
|
12108
12734
|
if (!solvedTerminal.path) {
|
|
12109
12735
|
console.warn(
|
|
12110
|
-
`No path found for connection ${solvedTerminal.connectionName} in section ${
|
|
12736
|
+
`No path found for connection ${solvedTerminal.connectionName} in section ${centerNodeId}`
|
|
12111
12737
|
);
|
|
12112
12738
|
continue;
|
|
12113
12739
|
}
|
|
@@ -12963,13 +13589,13 @@ function minimumDistanceBetweenSegments(A1, A2, B1, B2) {
|
|
|
12963
13589
|
if (segmentsIntersect(A1, A2, B1, B2)) {
|
|
12964
13590
|
return 0;
|
|
12965
13591
|
}
|
|
12966
|
-
const distA1 =
|
|
12967
|
-
const distA2 =
|
|
12968
|
-
const distB1 =
|
|
12969
|
-
const distB2 =
|
|
13592
|
+
const distA1 = pointToSegmentDistance6(A1, B1, B2);
|
|
13593
|
+
const distA2 = pointToSegmentDistance6(A2, B1, B2);
|
|
13594
|
+
const distB1 = pointToSegmentDistance6(B1, A1, A2);
|
|
13595
|
+
const distB2 = pointToSegmentDistance6(B2, A1, A2);
|
|
12970
13596
|
return Math.min(distA1, distA2, distB1, distB2);
|
|
12971
13597
|
}
|
|
12972
|
-
function
|
|
13598
|
+
function pointToSegmentDistance6(P, Q1, Q2) {
|
|
12973
13599
|
const v = { x: Q2.x - Q1.x, y: Q2.y - Q1.y };
|
|
12974
13600
|
const w = { x: P.x - Q1.x, y: P.y - Q1.y };
|
|
12975
13601
|
const c1 = dotProduct(w, v);
|
|
@@ -14471,8 +15097,8 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
14471
15097
|
nodeSolver;
|
|
14472
15098
|
nodeTargetMerger;
|
|
14473
15099
|
edgeSolver;
|
|
14474
|
-
|
|
14475
|
-
|
|
15100
|
+
initialPathingSolver;
|
|
15101
|
+
pathingOptimizer;
|
|
14476
15102
|
edgeToPortSegmentSolver;
|
|
14477
15103
|
colorMap;
|
|
14478
15104
|
segmentToPointSolver;
|
|
@@ -14559,12 +15185,28 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
14559
15185
|
(cms) => [cms.capacityNodes]
|
|
14560
15186
|
),
|
|
14561
15187
|
definePipelineStep(
|
|
14562
|
-
"
|
|
15188
|
+
"initialPathingSolver",
|
|
15189
|
+
CapacityPathingGreedySolver,
|
|
15190
|
+
(cms) => [
|
|
15191
|
+
{
|
|
15192
|
+
simpleRouteJson: cms.srjWithPointPairs,
|
|
15193
|
+
nodes: cms.capacityNodes,
|
|
15194
|
+
edges: cms.edgeSolver?.edges || [],
|
|
15195
|
+
colorMap: cms.colorMap,
|
|
15196
|
+
hyperParameters: {
|
|
15197
|
+
MAX_CAPACITY_FACTOR: 1
|
|
15198
|
+
}
|
|
15199
|
+
}
|
|
15200
|
+
]
|
|
15201
|
+
),
|
|
15202
|
+
definePipelineStep(
|
|
15203
|
+
"pathingOptimizer",
|
|
14563
15204
|
// CapacityPathingSolver5,
|
|
14564
15205
|
CapacityPathingMultiSectionSolver,
|
|
14565
15206
|
(cms) => [
|
|
14566
15207
|
// Replaced solver class
|
|
14567
15208
|
{
|
|
15209
|
+
initialPathingSolver: cms.initialPathingSolver,
|
|
14568
15210
|
simpleRouteJson: cms.srjWithPointPairs,
|
|
14569
15211
|
nodes: cms.capacityNodes,
|
|
14570
15212
|
edges: cms.edgeSolver?.edges || [],
|
|
@@ -14582,7 +15224,7 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
14582
15224
|
{
|
|
14583
15225
|
nodes: cms.capacityNodes,
|
|
14584
15226
|
edges: cms.edgeSolver?.edges || [],
|
|
14585
|
-
capacityPaths: cms.
|
|
15227
|
+
capacityPaths: cms.pathingOptimizer?.getCapacityPaths() || [],
|
|
14586
15228
|
colorMap: cms.colorMap
|
|
14587
15229
|
}
|
|
14588
15230
|
]
|
|
@@ -14741,7 +15383,8 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
14741
15383
|
const singleLayerNodeMergerViz = this.singleLayerNodeMerger?.visualize();
|
|
14742
15384
|
const strawSolverViz = this.strawSolver?.visualize();
|
|
14743
15385
|
const edgeViz = this.edgeSolver?.visualize();
|
|
14744
|
-
const
|
|
15386
|
+
const initialPathingViz = this.initialPathingSolver?.visualize();
|
|
15387
|
+
const pathingOptimizerViz = this.pathingOptimizer?.visualize();
|
|
14745
15388
|
const edgeToPortSegmentViz = this.edgeToPortSegmentSolver?.visualize();
|
|
14746
15389
|
const segmentToPointViz = this.segmentToPointSolver?.visualize();
|
|
14747
15390
|
const segmentOptimizationViz = this.unravelMultiSectionSolver?.visualize() ?? this.segmentToPointOptimizer?.visualize();
|
|
@@ -14796,7 +15439,8 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
14796
15439
|
singleLayerNodeMergerViz,
|
|
14797
15440
|
strawSolverViz,
|
|
14798
15441
|
edgeViz,
|
|
14799
|
-
|
|
15442
|
+
initialPathingViz,
|
|
15443
|
+
pathingOptimizerViz,
|
|
14800
15444
|
edgeToPortSegmentViz,
|
|
14801
15445
|
segmentToPointViz,
|
|
14802
15446
|
segmentOptimizationViz,
|
|
@@ -14838,9 +15482,9 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
14838
15482
|
}
|
|
14839
15483
|
return { lines };
|
|
14840
15484
|
}
|
|
14841
|
-
if (this.
|
|
15485
|
+
if (this.pathingOptimizer) {
|
|
14842
15486
|
const lines = [];
|
|
14843
|
-
for (const connection of this.
|
|
15487
|
+
for (const connection of this.pathingOptimizer.connectionsWithNodes) {
|
|
14844
15488
|
if (!connection.path) continue;
|
|
14845
15489
|
lines.push({
|
|
14846
15490
|
points: connection.path.map((n) => ({
|