@tscircuit/capacity-autorouter 0.0.62 → 0.0.64
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 +140 -2
- package/dist/index.js +622 -138
- package/dist/index.js.map +1 -1
- package/package.json +2 -2
package/dist/index.js
CHANGED
|
@@ -3721,8 +3721,54 @@ function seededRandom(seed) {
|
|
|
3721
3721
|
return result - Math.floor(result);
|
|
3722
3722
|
};
|
|
3723
3723
|
}
|
|
3724
|
+
var PRESHUFFLED_CASES = {
|
|
3725
|
+
1: [[0]],
|
|
3726
|
+
2: [
|
|
3727
|
+
[0, 1],
|
|
3728
|
+
[1, 0]
|
|
3729
|
+
],
|
|
3730
|
+
3: [
|
|
3731
|
+
[0, 1, 2],
|
|
3732
|
+
[2, 0, 1],
|
|
3733
|
+
[1, 0, 2],
|
|
3734
|
+
[0, 2, 1],
|
|
3735
|
+
[1, 2, 0],
|
|
3736
|
+
[2, 1, 0]
|
|
3737
|
+
],
|
|
3738
|
+
4: [
|
|
3739
|
+
[0, 1, 2, 3],
|
|
3740
|
+
[2, 0, 1, 3],
|
|
3741
|
+
[1, 3, 2, 0],
|
|
3742
|
+
[3, 0, 1, 2],
|
|
3743
|
+
[0, 2, 1, 3],
|
|
3744
|
+
[2, 1, 3, 0],
|
|
3745
|
+
[3, 0, 2, 1],
|
|
3746
|
+
[1, 2, 0, 3],
|
|
3747
|
+
[3, 1, 0, 2],
|
|
3748
|
+
[0, 3, 2, 1],
|
|
3749
|
+
[2, 3, 0, 1],
|
|
3750
|
+
[2, 3, 1, 0],
|
|
3751
|
+
[1, 2, 3, 0],
|
|
3752
|
+
[3, 1, 2, 0],
|
|
3753
|
+
[0, 1, 3, 2],
|
|
3754
|
+
[0, 2, 3, 1],
|
|
3755
|
+
[0, 3, 1, 2],
|
|
3756
|
+
[1, 0, 2, 3],
|
|
3757
|
+
[1, 0, 3, 2],
|
|
3758
|
+
[1, 3, 0, 2],
|
|
3759
|
+
[2, 0, 3, 1],
|
|
3760
|
+
[2, 1, 0, 3],
|
|
3761
|
+
[3, 2, 0, 1],
|
|
3762
|
+
[3, 2, 1, 0]
|
|
3763
|
+
]
|
|
3764
|
+
};
|
|
3724
3765
|
function cloneAndShuffleArray(arr, seed) {
|
|
3725
3766
|
if (seed === 0) return arr;
|
|
3767
|
+
if (arr.length <= 4) {
|
|
3768
|
+
const preshuffledOptions = PRESHUFFLED_CASES[arr.length];
|
|
3769
|
+
const preshuffledCase = preshuffledOptions[seed % preshuffledOptions.length];
|
|
3770
|
+
return preshuffledCase.map((orderIndex) => arr[orderIndex]);
|
|
3771
|
+
}
|
|
3726
3772
|
const random = seededRandom(seed);
|
|
3727
3773
|
const shuffled = arr.slice();
|
|
3728
3774
|
for (let i = 0; i < shuffled.length; i++) {
|
|
@@ -9639,6 +9685,30 @@ var SingleHighDensityRouteStitchSolver = class extends BaseSolver {
|
|
|
9639
9685
|
super();
|
|
9640
9686
|
this.remainingHdRoutes = [...opts.hdRoutes];
|
|
9641
9687
|
this.colorMap = opts.colorMap ?? {};
|
|
9688
|
+
if (opts.hdRoutes.length === 0) {
|
|
9689
|
+
this.start = opts.start;
|
|
9690
|
+
this.end = opts.end;
|
|
9691
|
+
const routePoints = [
|
|
9692
|
+
{ x: opts.start.x, y: opts.start.y, z: opts.start.z }
|
|
9693
|
+
];
|
|
9694
|
+
const vias = [];
|
|
9695
|
+
if (opts.start.z !== opts.end.z) {
|
|
9696
|
+
routePoints.push({ x: opts.start.x, y: opts.start.y, z: opts.end.z });
|
|
9697
|
+
vias.push({ x: opts.start.x, y: opts.start.y });
|
|
9698
|
+
}
|
|
9699
|
+
routePoints.push({ x: opts.end.x, y: opts.end.y, z: opts.end.z });
|
|
9700
|
+
this.mergedHdRoute = {
|
|
9701
|
+
connectionName: opts.connectionName,
|
|
9702
|
+
route: routePoints,
|
|
9703
|
+
vias,
|
|
9704
|
+
viaDiameter: opts.defaultViaDiameter ?? 0.6,
|
|
9705
|
+
// Use default or fallback
|
|
9706
|
+
traceThickness: opts.defaultTraceThickness ?? 0.15
|
|
9707
|
+
// Use default or fallback
|
|
9708
|
+
};
|
|
9709
|
+
this.solved = true;
|
|
9710
|
+
return;
|
|
9711
|
+
}
|
|
9642
9712
|
const { firstRoute } = this.getDisjointedRoute();
|
|
9643
9713
|
const firstRouteToStartDist = Math.min(
|
|
9644
9714
|
distance(firstRoute.route[0], opts.start),
|
|
@@ -9656,7 +9726,8 @@ var SingleHighDensityRouteStitchSolver = class extends BaseSolver {
|
|
|
9656
9726
|
this.end = opts.start;
|
|
9657
9727
|
}
|
|
9658
9728
|
this.mergedHdRoute = {
|
|
9659
|
-
connectionName: opts.connectionName
|
|
9729
|
+
connectionName: opts.connectionName,
|
|
9730
|
+
// Use mandatory connectionName
|
|
9660
9731
|
route: [
|
|
9661
9732
|
{
|
|
9662
9733
|
x: this.start.x,
|
|
@@ -9821,9 +9892,18 @@ var MultipleHighDensityRouteStitchSolver = class extends BaseSolver {
|
|
|
9821
9892
|
activeSolver = null;
|
|
9822
9893
|
mergedHdRoutes = [];
|
|
9823
9894
|
colorMap = {};
|
|
9895
|
+
defaultTraceThickness;
|
|
9896
|
+
defaultViaDiameter;
|
|
9824
9897
|
constructor(opts) {
|
|
9825
9898
|
super();
|
|
9826
9899
|
this.colorMap = opts.colorMap ?? {};
|
|
9900
|
+
if (opts.hdRoutes.length > 0) {
|
|
9901
|
+
this.defaultTraceThickness = opts.hdRoutes[0].traceThickness;
|
|
9902
|
+
this.defaultViaDiameter = opts.hdRoutes[0].viaDiameter;
|
|
9903
|
+
} else {
|
|
9904
|
+
this.defaultTraceThickness = 0.15;
|
|
9905
|
+
this.defaultViaDiameter = 0.6;
|
|
9906
|
+
}
|
|
9827
9907
|
this.unsolvedRoutes = opts.connections.map((c) => ({
|
|
9828
9908
|
connectionName: c.name,
|
|
9829
9909
|
hdRoutes: opts.hdRoutes.filter((r) => r.connectionName === c.name),
|
|
@@ -9860,7 +9940,9 @@ var MultipleHighDensityRouteStitchSolver = class extends BaseSolver {
|
|
|
9860
9940
|
hdRoutes: unsolvedRoute.hdRoutes,
|
|
9861
9941
|
start: unsolvedRoute.start,
|
|
9862
9942
|
end: unsolvedRoute.end,
|
|
9863
|
-
colorMap: this.colorMap
|
|
9943
|
+
colorMap: this.colorMap,
|
|
9944
|
+
defaultTraceThickness: this.defaultTraceThickness,
|
|
9945
|
+
defaultViaDiameter: this.defaultViaDiameter
|
|
9864
9946
|
});
|
|
9865
9947
|
}
|
|
9866
9948
|
visualize() {
|
|
@@ -10937,6 +11019,8 @@ import objectHash from "object-hash";
|
|
|
10937
11019
|
|
|
10938
11020
|
// lib/cache/InMemoryCache.ts
|
|
10939
11021
|
var InMemoryCache = class {
|
|
11022
|
+
cacheHitsByPrefix = {};
|
|
11023
|
+
cacheMissesByPrefix = {};
|
|
10940
11024
|
isSyncCache = true;
|
|
10941
11025
|
cacheHits = 0;
|
|
10942
11026
|
cacheMisses = 0;
|
|
@@ -11002,6 +11086,8 @@ var LocalStorageCache = class {
|
|
|
11002
11086
|
isSyncCache = true;
|
|
11003
11087
|
cacheHits = 0;
|
|
11004
11088
|
cacheMisses = 0;
|
|
11089
|
+
cacheHitsByPrefix = {};
|
|
11090
|
+
cacheMissesByPrefix = {};
|
|
11005
11091
|
constructor() {
|
|
11006
11092
|
if (typeof localStorage === "undefined") {
|
|
11007
11093
|
console.warn(
|
|
@@ -11026,14 +11112,20 @@ var LocalStorageCache = class {
|
|
|
11026
11112
|
if (cachedItem !== null) {
|
|
11027
11113
|
const solution = JSON.parse(cachedItem);
|
|
11028
11114
|
this.cacheHits++;
|
|
11115
|
+
const prefix = cacheKey.split(":")[0];
|
|
11116
|
+
this.cacheHitsByPrefix[prefix] = (this.cacheHitsByPrefix[prefix] || 0) + 1;
|
|
11029
11117
|
return solution;
|
|
11030
11118
|
} else {
|
|
11031
11119
|
this.cacheMisses++;
|
|
11120
|
+
const prefix = cacheKey.split(":")[0];
|
|
11121
|
+
this.cacheMissesByPrefix[prefix] = (this.cacheMissesByPrefix[prefix] || 0) + 1;
|
|
11032
11122
|
return void 0;
|
|
11033
11123
|
}
|
|
11034
11124
|
} catch (error) {
|
|
11035
11125
|
console.error(`Error getting cached solution sync for ${key}:`, error);
|
|
11036
11126
|
this.cacheMisses++;
|
|
11127
|
+
const prefix = cacheKey.split(":")[0];
|
|
11128
|
+
this.cacheMissesByPrefix[prefix] = (this.cacheMissesByPrefix[prefix] || 0) + 1;
|
|
11037
11129
|
return void 0;
|
|
11038
11130
|
}
|
|
11039
11131
|
}
|
|
@@ -11098,6 +11190,8 @@ var LocalStorageCache = class {
|
|
|
11098
11190
|
} finally {
|
|
11099
11191
|
this.cacheHits = 0;
|
|
11100
11192
|
this.cacheMisses = 0;
|
|
11193
|
+
this.cacheHitsByPrefix = {};
|
|
11194
|
+
this.cacheMissesByPrefix = {};
|
|
11101
11195
|
}
|
|
11102
11196
|
}
|
|
11103
11197
|
getAllCacheKeys() {
|
|
@@ -11119,6 +11213,12 @@ function getGlobalLocalStorageCache() {
|
|
|
11119
11213
|
}
|
|
11120
11214
|
return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE;
|
|
11121
11215
|
}
|
|
11216
|
+
function getGlobalInMemoryCache() {
|
|
11217
|
+
if (!globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE) {
|
|
11218
|
+
setupGlobalCaches();
|
|
11219
|
+
}
|
|
11220
|
+
return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE;
|
|
11221
|
+
}
|
|
11122
11222
|
function setupGlobalCaches() {
|
|
11123
11223
|
globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE ??= new LocalStorageCache();
|
|
11124
11224
|
globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE ??= new InMemoryCache();
|
|
@@ -12521,6 +12621,21 @@ var calculateNodeProbabilityOfFailure2 = (usedCapacity, totalCapacity, layerCoun
|
|
|
12521
12621
|
const adjustedRatio = ratioOverTotal - 1;
|
|
12522
12622
|
return 1 - Math.exp(-k * adjustedRatio);
|
|
12523
12623
|
};
|
|
12624
|
+
var calculateSingleNodeLogSuccessProbability = (usedCapacity, totalCapacity, node) => {
|
|
12625
|
+
if (node._containsTarget) return 0;
|
|
12626
|
+
if (usedCapacity <= totalCapacity) return 0;
|
|
12627
|
+
const probabilityOfFailure = calculateNodeProbabilityOfFailure2(
|
|
12628
|
+
usedCapacity,
|
|
12629
|
+
totalCapacity,
|
|
12630
|
+
node.availableZ.length
|
|
12631
|
+
);
|
|
12632
|
+
const probabilityOfSuccess = 1 - probabilityOfFailure;
|
|
12633
|
+
if (probabilityOfSuccess <= 0) {
|
|
12634
|
+
return -1e9;
|
|
12635
|
+
} else {
|
|
12636
|
+
return Math.log(probabilityOfSuccess);
|
|
12637
|
+
}
|
|
12638
|
+
};
|
|
12524
12639
|
var computeSectionScore = ({
|
|
12525
12640
|
totalNodeCapacityMap,
|
|
12526
12641
|
usedNodeCapacityMap,
|
|
@@ -12534,21 +12649,13 @@ var computeSectionScore = ({
|
|
|
12534
12649
|
if (!totalNodeCapacityMap.has(nodeId)) continue;
|
|
12535
12650
|
const node = nodeMap.get(nodeId);
|
|
12536
12651
|
if (!node) continue;
|
|
12537
|
-
if (node._containsTarget) continue;
|
|
12538
12652
|
const totalCapacity = totalNodeCapacityMap.get(nodeId);
|
|
12539
12653
|
const usedCapacity = usedNodeCapacityMap.get(nodeId) ?? 0;
|
|
12540
|
-
|
|
12541
|
-
const probabilityOfFailure = calculateNodeProbabilityOfFailure2(
|
|
12654
|
+
logProbabilityOfSuccessSum += calculateSingleNodeLogSuccessProbability(
|
|
12542
12655
|
usedCapacity,
|
|
12543
12656
|
totalCapacity,
|
|
12544
|
-
node
|
|
12657
|
+
node
|
|
12545
12658
|
);
|
|
12546
|
-
const probabilityOfSuccess = 1 - probabilityOfFailure;
|
|
12547
|
-
if (probabilityOfSuccess <= 0) {
|
|
12548
|
-
logProbabilityOfSuccessSum += -1e9;
|
|
12549
|
-
} else {
|
|
12550
|
-
logProbabilityOfSuccessSum += Math.log(probabilityOfSuccess);
|
|
12551
|
-
}
|
|
12552
12659
|
}
|
|
12553
12660
|
return logProbabilityOfSuccessSum;
|
|
12554
12661
|
};
|
|
@@ -12729,9 +12836,9 @@ ${percent}% (Pf: ${(probabilityOfFailure * 100).toFixed(1)}%)`;
|
|
|
12729
12836
|
x: x + offset.x,
|
|
12730
12837
|
y: y + offset.y
|
|
12731
12838
|
})),
|
|
12732
|
-
strokeColor: safeTransparentize(pathColor, 0.2)
|
|
12839
|
+
strokeColor: safeTransparentize(pathColor, 0.2)
|
|
12733
12840
|
// Make solved paths semi-transparent
|
|
12734
|
-
strokeWidth: 0.03
|
|
12841
|
+
// strokeWidth: 0.03,
|
|
12735
12842
|
});
|
|
12736
12843
|
}
|
|
12737
12844
|
});
|
|
@@ -12739,6 +12846,72 @@ ${percent}% (Pf: ${(probabilityOfFailure * 100).toFixed(1)}%)`;
|
|
|
12739
12846
|
return graphics;
|
|
12740
12847
|
}
|
|
12741
12848
|
|
|
12849
|
+
// lib/solvers/CapacityPathingSectionSolver/computeSectionNodesTerminalsAndEdges.ts
|
|
12850
|
+
var computeSectionNodesTerminalsAndEdges = (opts) => {
|
|
12851
|
+
const {
|
|
12852
|
+
centerNodeId,
|
|
12853
|
+
connectionsWithNodes,
|
|
12854
|
+
nodeMap,
|
|
12855
|
+
edges,
|
|
12856
|
+
nodeEdgeMap,
|
|
12857
|
+
expansionDegrees
|
|
12858
|
+
} = opts;
|
|
12859
|
+
const sectionNodeIds = /* @__PURE__ */ new Set();
|
|
12860
|
+
const queue = [
|
|
12861
|
+
{ nodeId: centerNodeId, depth: 0 }
|
|
12862
|
+
];
|
|
12863
|
+
sectionNodeIds.add(centerNodeId);
|
|
12864
|
+
let head = 0;
|
|
12865
|
+
while (head < queue.length) {
|
|
12866
|
+
const { nodeId, depth } = queue[head++];
|
|
12867
|
+
if (depth >= expansionDegrees) continue;
|
|
12868
|
+
const neighbors = nodeEdgeMap.get(nodeId)?.flatMap((edge) => edge.nodeIds.filter((id) => id !== nodeId)) ?? [];
|
|
12869
|
+
for (const neighborId of neighbors) {
|
|
12870
|
+
if (!sectionNodeIds.has(neighborId)) {
|
|
12871
|
+
sectionNodeIds.add(neighborId);
|
|
12872
|
+
queue.push({ nodeId: neighborId, depth: depth + 1 });
|
|
12873
|
+
}
|
|
12874
|
+
}
|
|
12875
|
+
}
|
|
12876
|
+
const sectionNodes = Array.from(sectionNodeIds).map((id) => nodeMap.get(id));
|
|
12877
|
+
const sectionEdges = edges.filter((edge) => {
|
|
12878
|
+
const [nodeIdA, nodeIdB] = edge.nodeIds;
|
|
12879
|
+
return sectionNodeIds.has(nodeIdA) && sectionNodeIds.has(nodeIdB);
|
|
12880
|
+
});
|
|
12881
|
+
const sectionConnectionTerminals = [];
|
|
12882
|
+
for (const conn of connectionsWithNodes) {
|
|
12883
|
+
if (!conn.path) continue;
|
|
12884
|
+
let startNodeId = null;
|
|
12885
|
+
let endNodeId = null;
|
|
12886
|
+
for (const node of conn.path) {
|
|
12887
|
+
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
12888
|
+
startNodeId = node.capacityMeshNodeId;
|
|
12889
|
+
break;
|
|
12890
|
+
}
|
|
12891
|
+
}
|
|
12892
|
+
for (let i = conn.path.length - 1; i >= 0; i--) {
|
|
12893
|
+
const node = conn.path[i];
|
|
12894
|
+
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
12895
|
+
endNodeId = node.capacityMeshNodeId;
|
|
12896
|
+
break;
|
|
12897
|
+
}
|
|
12898
|
+
}
|
|
12899
|
+
if (startNodeId && endNodeId) {
|
|
12900
|
+
sectionConnectionTerminals.push({
|
|
12901
|
+
connectionName: conn.connection.name,
|
|
12902
|
+
startNodeId,
|
|
12903
|
+
endNodeId
|
|
12904
|
+
});
|
|
12905
|
+
}
|
|
12906
|
+
}
|
|
12907
|
+
return {
|
|
12908
|
+
sectionConnectionTerminals,
|
|
12909
|
+
sectionNodes,
|
|
12910
|
+
sectionEdges,
|
|
12911
|
+
centerNodeId
|
|
12912
|
+
};
|
|
12913
|
+
};
|
|
12914
|
+
|
|
12742
12915
|
// lib/solvers/CapacityPathingSectionSolver/CapacityPathingSingleSectionSolver.ts
|
|
12743
12916
|
var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
12744
12917
|
GREEDY_MULTIPLIER = 1.5;
|
|
@@ -12752,7 +12925,10 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
12752
12925
|
colorMap;
|
|
12753
12926
|
usedNodeCapacityMap;
|
|
12754
12927
|
// Tracks capacity usage *within this solver's run*
|
|
12928
|
+
totalNodeCapacityMap;
|
|
12929
|
+
// Added: Stores total capacity for each node
|
|
12755
12930
|
centerNodeId;
|
|
12931
|
+
currentSectionScore = 0;
|
|
12756
12932
|
MAX_CANDIDATES_IN_MEMORY = 1e4;
|
|
12757
12933
|
// A* state
|
|
12758
12934
|
currentConnectionIndex = 0;
|
|
@@ -12773,14 +12949,28 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
12773
12949
|
this.sectionConnectionTerminals = params.sectionConnectionTerminals.map(
|
|
12774
12950
|
(t) => ({ ...t, path: void 0 })
|
|
12775
12951
|
);
|
|
12776
|
-
this.nodeMap = new Map(
|
|
12777
|
-
this.sectionNodes.map((n) => [n.capacityMeshNodeId, n])
|
|
12778
|
-
);
|
|
12952
|
+
this.nodeMap = params.nodeMap ?? new Map(this.sectionNodes.map((n) => [n.capacityMeshNodeId, n]));
|
|
12779
12953
|
this.nodeEdgeMap = params.nodeEdgeMap ?? getNodeEdgeMap(this.sectionEdges);
|
|
12780
12954
|
this.colorMap = params.colorMap ?? {};
|
|
12781
12955
|
this.usedNodeCapacityMap = new Map(
|
|
12782
12956
|
this.sectionNodes.map((node) => [node.capacityMeshNodeId, 0])
|
|
12783
12957
|
);
|
|
12958
|
+
this.totalNodeCapacityMap = new Map(
|
|
12959
|
+
this.sectionNodes.map((node) => [
|
|
12960
|
+
node.capacityMeshNodeId,
|
|
12961
|
+
this.getTotalCapacity(node)
|
|
12962
|
+
])
|
|
12963
|
+
);
|
|
12964
|
+
const initialSectionNodeIds = new Set(
|
|
12965
|
+
this.sectionNodes.map((n) => n.capacityMeshNodeId)
|
|
12966
|
+
);
|
|
12967
|
+
this.currentSectionScore = computeSectionScore({
|
|
12968
|
+
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
12969
|
+
usedNodeCapacityMap: this.usedNodeCapacityMap,
|
|
12970
|
+
// Reflects initial capacities
|
|
12971
|
+
nodeMap: this.nodeMap,
|
|
12972
|
+
sectionNodeIds: initialSectionNodeIds
|
|
12973
|
+
});
|
|
12784
12974
|
if (params.hyperParameters?.SHUFFLE_SEED) {
|
|
12785
12975
|
this.sectionConnectionTerminals = cloneAndShuffleArray(
|
|
12786
12976
|
this.sectionConnectionTerminals,
|
|
@@ -12860,15 +13050,40 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
12860
13050
|
}
|
|
12861
13051
|
// Adapted from CapacityPathingSolver - uses section's capacity map
|
|
12862
13052
|
reduceCapacityAlongPath(path) {
|
|
12863
|
-
for (const
|
|
12864
|
-
if (this.usedNodeCapacityMap.has(
|
|
12865
|
-
|
|
12866
|
-
|
|
12867
|
-
|
|
13053
|
+
for (const pathNode of path) {
|
|
13054
|
+
if (this.usedNodeCapacityMap.has(pathNode.capacityMeshNodeId)) {
|
|
13055
|
+
const nodeId = pathNode.capacityMeshNodeId;
|
|
13056
|
+
const nodeInSection = this.nodeMap.get(nodeId);
|
|
13057
|
+
if (!nodeInSection) {
|
|
13058
|
+
console.warn(
|
|
13059
|
+
`Node ${nodeId} from path not found in section's nodeMap during score update.`
|
|
13060
|
+
);
|
|
13061
|
+
continue;
|
|
13062
|
+
}
|
|
13063
|
+
const totalCapacity = this.totalNodeCapacityMap.get(nodeId);
|
|
13064
|
+
const oldUsedCapacity = this.usedNodeCapacityMap.get(nodeId) ?? 0;
|
|
13065
|
+
const oldNodeScoreContribution = calculateSingleNodeLogSuccessProbability(
|
|
13066
|
+
oldUsedCapacity,
|
|
13067
|
+
totalCapacity,
|
|
13068
|
+
nodeInSection
|
|
13069
|
+
// Use the node object from the section's map
|
|
13070
|
+
);
|
|
13071
|
+
this.currentSectionScore -= oldNodeScoreContribution;
|
|
13072
|
+
const newUsedCapacity = oldUsedCapacity + 1;
|
|
13073
|
+
this.usedNodeCapacityMap.set(nodeId, newUsedCapacity);
|
|
13074
|
+
const newNodeScoreContribution = calculateSingleNodeLogSuccessProbability(
|
|
13075
|
+
newUsedCapacity,
|
|
13076
|
+
totalCapacity,
|
|
13077
|
+
nodeInSection
|
|
13078
|
+
// Use the node object from the section's map
|
|
12868
13079
|
);
|
|
13080
|
+
this.currentSectionScore += newNodeScoreContribution;
|
|
12869
13081
|
}
|
|
12870
13082
|
}
|
|
12871
13083
|
}
|
|
13084
|
+
getSolvedSectionScore() {
|
|
13085
|
+
return this.currentSectionScore;
|
|
13086
|
+
}
|
|
12872
13087
|
_step() {
|
|
12873
13088
|
const currentTerminal = this.sectionConnectionTerminals[this.currentConnectionIndex];
|
|
12874
13089
|
if (!currentTerminal) {
|
|
@@ -13070,6 +13285,7 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
13070
13285
|
var CapacityPathingSingleSectionPathingSolver = CapacityPathingSingleSectionSolver;
|
|
13071
13286
|
|
|
13072
13287
|
// lib/solvers/CapacityPathingSectionSolver/HyperCapacityPathingSingleSectionSolver.ts
|
|
13288
|
+
var range = (n) => Array.from({ length: n }, (_, i) => i);
|
|
13073
13289
|
var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSupervisorSolver {
|
|
13074
13290
|
constructorParams;
|
|
13075
13291
|
winningSolver;
|
|
@@ -13078,14 +13294,24 @@ var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSuperv
|
|
|
13078
13294
|
this.MAX_ITERATIONS = 1e5;
|
|
13079
13295
|
this.constructorParams = params;
|
|
13080
13296
|
}
|
|
13297
|
+
// TODO this needs to use the section score, ideally incorporating the current best candidate
|
|
13298
|
+
// of the paths being explored inside the single section
|
|
13081
13299
|
computeG(solver) {
|
|
13082
|
-
return solver.
|
|
13300
|
+
return -solver.getSolvedSectionScore();
|
|
13083
13301
|
}
|
|
13084
13302
|
computeH(solver) {
|
|
13085
|
-
return
|
|
13303
|
+
return 0;
|
|
13086
13304
|
}
|
|
13087
13305
|
getCombinationDefs() {
|
|
13088
|
-
|
|
13306
|
+
const numConnections = this.constructorParams.sectionConnectionTerminals.length;
|
|
13307
|
+
if (numConnections === 2) {
|
|
13308
|
+
return [["orderings2_for2"]];
|
|
13309
|
+
} else if (numConnections === 3) {
|
|
13310
|
+
return [["orderings6_for3"]];
|
|
13311
|
+
} else if (numConnections === 4) {
|
|
13312
|
+
return [["orderings24_for4"]];
|
|
13313
|
+
}
|
|
13314
|
+
return [["orderings30"]];
|
|
13089
13315
|
}
|
|
13090
13316
|
getFailureMessage() {
|
|
13091
13317
|
return `All CapacityPathingSingleSection solvers failed for "${this.centerNodeId}"`;
|
|
@@ -13093,39 +13319,28 @@ var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSuperv
|
|
|
13093
13319
|
getHyperParameterDefs() {
|
|
13094
13320
|
return [
|
|
13095
13321
|
{
|
|
13096
|
-
name: "
|
|
13097
|
-
possibleValues:
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
|
|
13111
|
-
|
|
13112
|
-
|
|
13113
|
-
|
|
13114
|
-
|
|
13115
|
-
|
|
13116
|
-
|
|
13117
|
-
|
|
13118
|
-
},
|
|
13119
|
-
{
|
|
13120
|
-
SHUFFLE_SEED: 7
|
|
13121
|
-
},
|
|
13122
|
-
{
|
|
13123
|
-
SHUFFLE_SEED: 8
|
|
13124
|
-
},
|
|
13125
|
-
{
|
|
13126
|
-
SHUFFLE_SEED: 9
|
|
13127
|
-
}
|
|
13128
|
-
]
|
|
13322
|
+
name: "orderings2_for2",
|
|
13323
|
+
possibleValues: range(2).map((i) => ({
|
|
13324
|
+
SHUFFLE_SEED: i
|
|
13325
|
+
}))
|
|
13326
|
+
},
|
|
13327
|
+
{
|
|
13328
|
+
name: "orderings6_for3",
|
|
13329
|
+
possibleValues: range(6).map((i) => ({
|
|
13330
|
+
SHUFFLE_SEED: i
|
|
13331
|
+
}))
|
|
13332
|
+
},
|
|
13333
|
+
{
|
|
13334
|
+
name: "orderings24_for4",
|
|
13335
|
+
possibleValues: range(24).map((i) => ({
|
|
13336
|
+
SHUFFLE_SEED: i
|
|
13337
|
+
}))
|
|
13338
|
+
},
|
|
13339
|
+
{
|
|
13340
|
+
name: "orderings30",
|
|
13341
|
+
possibleValues: range(30).map((i) => ({
|
|
13342
|
+
SHUFFLE_SEED: i
|
|
13343
|
+
}))
|
|
13129
13344
|
}
|
|
13130
13345
|
];
|
|
13131
13346
|
}
|
|
@@ -13154,70 +13369,320 @@ var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSuperv
|
|
|
13154
13369
|
}
|
|
13155
13370
|
};
|
|
13156
13371
|
|
|
13157
|
-
// lib/solvers/CapacityPathingSectionSolver/
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
|
|
13173
|
-
|
|
13174
|
-
|
|
13175
|
-
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13372
|
+
// lib/solvers/CapacityPathingSectionSolver/CachedHyperCapacityPathingSingleSectionSolver.ts
|
|
13373
|
+
import objectHash2 from "object-hash";
|
|
13374
|
+
var roundCapacity = (capacity) => Math.floor(capacity * 10) / 10;
|
|
13375
|
+
var CachedHyperCapacityPathingSingleSectionSolver = class extends HyperCapacityPathingSingleSectionSolver {
|
|
13376
|
+
cacheHit = false;
|
|
13377
|
+
cacheProvider;
|
|
13378
|
+
hasAttemptedToUseCache = false;
|
|
13379
|
+
sectionNodeIdSet;
|
|
13380
|
+
cachedSectionConnectionTerminals = null;
|
|
13381
|
+
sectionScore = 0;
|
|
13382
|
+
constructor(params) {
|
|
13383
|
+
params.nodeMap = params.nodeMap ?? new Map(params.sectionNodes.map((n) => [n.capacityMeshNodeId, n]));
|
|
13384
|
+
super(params);
|
|
13385
|
+
this.sectionNodeIdSet = new Set(
|
|
13386
|
+
params.sectionNodes.map((sn) => sn.capacityMeshNodeId)
|
|
13387
|
+
);
|
|
13388
|
+
this.cacheProvider = params.cacheProvider === void 0 ? getGlobalInMemoryCache() : params.cacheProvider;
|
|
13389
|
+
}
|
|
13390
|
+
_step() {
|
|
13391
|
+
if (!this.hasAttemptedToUseCache && this.cacheProvider) {
|
|
13392
|
+
if (this.attemptToUseCacheSync()) return;
|
|
13393
|
+
}
|
|
13394
|
+
super._step();
|
|
13395
|
+
if ((this.solved || this.failed) && this.cacheProvider) {
|
|
13396
|
+
this.saveToCacheSync();
|
|
13182
13397
|
}
|
|
13183
13398
|
}
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
const
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13190
|
-
|
|
13191
|
-
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13197
|
-
|
|
13399
|
+
_computeBfsOrderingOfNodesInSection() {
|
|
13400
|
+
const seenNodeIds = new Set(this.constructorParams.centerNodeId);
|
|
13401
|
+
const ordering = [];
|
|
13402
|
+
const candidates = [
|
|
13403
|
+
{
|
|
13404
|
+
ancestorCapacitySum: 0,
|
|
13405
|
+
capacity: 0,
|
|
13406
|
+
g: 0,
|
|
13407
|
+
capacityMeshNodeId: this.constructorParams.centerNodeId
|
|
13408
|
+
}
|
|
13409
|
+
];
|
|
13410
|
+
while (candidates.length > 0) {
|
|
13411
|
+
candidates.sort((a, b) => b.g - a.g);
|
|
13412
|
+
const candidate = candidates.pop();
|
|
13413
|
+
if (!candidate) break;
|
|
13414
|
+
ordering.push(candidate.capacityMeshNodeId);
|
|
13415
|
+
const neighborNodeIds = this.constructorParams.nodeEdgeMap.get(candidate.capacityMeshNodeId).flatMap((edge) => edge.nodeIds).filter((nodeId) => !seenNodeIds.has(nodeId)).filter((nodeId) => this.sectionNodeIdSet.has(nodeId));
|
|
13416
|
+
for (const neighborNodeId of neighborNodeIds) {
|
|
13417
|
+
seenNodeIds.add(neighborNodeId);
|
|
13418
|
+
const neighbor = this.constructorParams.nodeMap.get(neighborNodeId);
|
|
13419
|
+
const capacity = getTunedTotalCapacity1(neighbor);
|
|
13420
|
+
candidates.push({
|
|
13421
|
+
ancestorCapacitySum: candidate.g,
|
|
13422
|
+
capacity,
|
|
13423
|
+
g: candidate.g + capacity,
|
|
13424
|
+
capacityMeshNodeId: neighborNodeId
|
|
13425
|
+
});
|
|
13198
13426
|
}
|
|
13199
13427
|
}
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13204
|
-
|
|
13428
|
+
return ordering;
|
|
13429
|
+
}
|
|
13430
|
+
computeCacheKeyAndTransform() {
|
|
13431
|
+
const nodeOrdering = this._computeBfsOrderingOfNodesInSection();
|
|
13432
|
+
const realToCacheSpaceNodeIdMap = /* @__PURE__ */ new Map();
|
|
13433
|
+
const cacheSpaceToRealNodeIdMap = /* @__PURE__ */ new Map();
|
|
13434
|
+
nodeOrdering.forEach((realNodeId, i) => {
|
|
13435
|
+
const cacheNodeId = `node${i}`;
|
|
13436
|
+
realToCacheSpaceNodeIdMap.set(realNodeId, cacheNodeId);
|
|
13437
|
+
cacheSpaceToRealNodeIdMap.set(cacheNodeId, realNodeId);
|
|
13438
|
+
});
|
|
13439
|
+
const node_capacity_map = {};
|
|
13440
|
+
for (const realNodeId of nodeOrdering) {
|
|
13441
|
+
const cacheNodeId = realToCacheSpaceNodeIdMap.get(realNodeId);
|
|
13442
|
+
const node = this.constructorParams.nodeMap.get(realNodeId);
|
|
13443
|
+
const capacity = getTunedTotalCapacity1(node);
|
|
13444
|
+
node_capacity_map[cacheNodeId] = roundCapacity(capacity).toFixed(
|
|
13445
|
+
1
|
|
13446
|
+
);
|
|
13447
|
+
}
|
|
13448
|
+
const node_edge_map_set = /* @__PURE__ */ new Set();
|
|
13449
|
+
const node_edge_map = [];
|
|
13450
|
+
for (const realNodeId1 of nodeOrdering) {
|
|
13451
|
+
const cacheNodeId1 = realToCacheSpaceNodeIdMap.get(realNodeId1);
|
|
13452
|
+
const neighbors = this.constructorParams.nodeEdgeMap.get(realNodeId1) ?? [];
|
|
13453
|
+
for (const edge of neighbors) {
|
|
13454
|
+
const realNodeId2 = edge.nodeIds.find((id) => id !== realNodeId1);
|
|
13455
|
+
if (this.sectionNodeIdSet.has(realNodeId2)) {
|
|
13456
|
+
const cacheNodeId2 = realToCacheSpaceNodeIdMap.get(realNodeId2);
|
|
13457
|
+
const pair = [cacheNodeId1, cacheNodeId2].sort();
|
|
13458
|
+
const pairKey = `${pair[0]}-${pair[1]}`;
|
|
13459
|
+
if (!node_edge_map_set.has(pairKey)) {
|
|
13460
|
+
node_edge_map.push(pair);
|
|
13461
|
+
node_edge_map_set.add(pairKey);
|
|
13462
|
+
}
|
|
13463
|
+
}
|
|
13205
13464
|
}
|
|
13206
13465
|
}
|
|
13207
|
-
|
|
13208
|
-
|
|
13209
|
-
|
|
13210
|
-
|
|
13211
|
-
|
|
13466
|
+
node_edge_map.sort((a, b) => {
|
|
13467
|
+
if (a[0] !== b[0]) return a[0].localeCompare(b[0]);
|
|
13468
|
+
return a[1].localeCompare(b[1]);
|
|
13469
|
+
});
|
|
13470
|
+
const terminals = {};
|
|
13471
|
+
const cacheSpaceToRealConnectionId = /* @__PURE__ */ new Map();
|
|
13472
|
+
for (const conn of this.constructorParams.sectionConnectionTerminals) {
|
|
13473
|
+
const cacheStartNodeId = realToCacheSpaceNodeIdMap.get(conn.startNodeId);
|
|
13474
|
+
const cacheEndNodeId = realToCacheSpaceNodeIdMap.get(conn.endNodeId);
|
|
13475
|
+
const [sortedStartId, sortedEndId] = [
|
|
13476
|
+
cacheStartNodeId,
|
|
13477
|
+
cacheEndNodeId
|
|
13478
|
+
].sort();
|
|
13479
|
+
const cacheSpaceConnectionId = `${sortedStartId}->${sortedEndId}`;
|
|
13480
|
+
terminals[cacheSpaceConnectionId] = {
|
|
13481
|
+
start: sortedStartId,
|
|
13482
|
+
end: sortedEndId
|
|
13483
|
+
};
|
|
13484
|
+
cacheSpaceToRealConnectionId.set(
|
|
13485
|
+
cacheSpaceConnectionId,
|
|
13486
|
+
// Use the canonically sorted key
|
|
13487
|
+
conn.connectionName
|
|
13488
|
+
);
|
|
13489
|
+
}
|
|
13490
|
+
const cacheKeyContent = {
|
|
13491
|
+
node_capacity_map,
|
|
13492
|
+
node_edge_map,
|
|
13493
|
+
terminals
|
|
13494
|
+
};
|
|
13495
|
+
const cacheKey = `capacitypathing:${objectHash2(cacheKeyContent)}`;
|
|
13496
|
+
const cacheToSolveSpaceTransform = {
|
|
13497
|
+
cacheSpaceToRealConnectionId,
|
|
13498
|
+
cacheSpaceToRealNodeId: cacheSpaceToRealNodeIdMap
|
|
13499
|
+
};
|
|
13500
|
+
this.cacheKey = cacheKey;
|
|
13501
|
+
this.cacheToSolveSpaceTransform = cacheToSolveSpaceTransform;
|
|
13502
|
+
return { cacheKey, cacheToSolveSpaceTransform };
|
|
13503
|
+
}
|
|
13504
|
+
applyCachedSolution(cachedSolution) {
|
|
13505
|
+
if (!this.cacheToSolveSpaceTransform) {
|
|
13506
|
+
console.error(
|
|
13507
|
+
"Cache transform not available, cannot apply cached solution."
|
|
13508
|
+
);
|
|
13509
|
+
this.failed = true;
|
|
13510
|
+
return;
|
|
13511
|
+
}
|
|
13512
|
+
if (!cachedSolution.success) {
|
|
13513
|
+
this.failed = true;
|
|
13514
|
+
this.cacheHit = true;
|
|
13515
|
+
return;
|
|
13516
|
+
}
|
|
13517
|
+
this.cachedSectionConnectionTerminals = [];
|
|
13518
|
+
const { cacheSpaceToRealNodeId, cacheSpaceToRealConnectionId } = this.cacheToSolveSpaceTransform;
|
|
13519
|
+
for (const [cacheConnId, cachePathNodeIds] of Object.entries(
|
|
13520
|
+
cachedSolution.solutionPaths
|
|
13521
|
+
)) {
|
|
13522
|
+
const realConnectionName = cacheSpaceToRealConnectionId.get(
|
|
13523
|
+
cacheConnId
|
|
13524
|
+
);
|
|
13525
|
+
if (!realConnectionName) {
|
|
13526
|
+
console.warn(`Could not find real connection name for ${cacheConnId}`);
|
|
13527
|
+
continue;
|
|
13528
|
+
}
|
|
13529
|
+
const originalTerminal = this.constructorParams.sectionConnectionTerminals.find(
|
|
13530
|
+
(t) => t.connectionName === realConnectionName
|
|
13531
|
+
);
|
|
13532
|
+
if (!originalTerminal) {
|
|
13533
|
+
console.warn(
|
|
13534
|
+
`Could not find original terminal for connection name ${realConnectionName}`
|
|
13535
|
+
);
|
|
13536
|
+
continue;
|
|
13537
|
+
}
|
|
13538
|
+
const realPathNodes = cachePathNodeIds.map(
|
|
13539
|
+
(cacheNodeId) => {
|
|
13540
|
+
const realNodeId = cacheSpaceToRealNodeId.get(cacheNodeId);
|
|
13541
|
+
if (!realNodeId) {
|
|
13542
|
+
throw new Error(
|
|
13543
|
+
`Could not map cache node ID ${cacheNodeId} to real node ID for connection ${realConnectionName}`
|
|
13544
|
+
);
|
|
13545
|
+
}
|
|
13546
|
+
const node = this.constructorParams.nodeMap.get(realNodeId);
|
|
13547
|
+
if (!node) {
|
|
13548
|
+
throw new Error(
|
|
13549
|
+
`Could not find node with ID ${realNodeId} in nodeMap for connection ${realConnectionName}`
|
|
13550
|
+
);
|
|
13551
|
+
}
|
|
13552
|
+
return node;
|
|
13553
|
+
}
|
|
13554
|
+
);
|
|
13555
|
+
this.cachedSectionConnectionTerminals.push({
|
|
13556
|
+
...originalTerminal,
|
|
13557
|
+
path: realPathNodes
|
|
13212
13558
|
});
|
|
13213
13559
|
}
|
|
13560
|
+
this.sectionScore = cachedSolution.sectionScore;
|
|
13561
|
+
this.solved = true;
|
|
13562
|
+
this.cacheHit = true;
|
|
13563
|
+
}
|
|
13564
|
+
attemptToUseCacheSync() {
|
|
13565
|
+
this.hasAttemptedToUseCache = true;
|
|
13566
|
+
if (!this.cacheProvider?.isSyncCache) {
|
|
13567
|
+
console.log(
|
|
13568
|
+
"Cache provider is not synchronous, skipping sync cache check."
|
|
13569
|
+
);
|
|
13570
|
+
return false;
|
|
13571
|
+
}
|
|
13572
|
+
if (!this.cacheKey) {
|
|
13573
|
+
this.computeCacheKeyAndTransform();
|
|
13574
|
+
}
|
|
13575
|
+
if (!this.cacheKey) {
|
|
13576
|
+
console.error("Failed to compute cache key.");
|
|
13577
|
+
return false;
|
|
13578
|
+
}
|
|
13579
|
+
try {
|
|
13580
|
+
const cachedSolution = this.cacheProvider.getCachedSolutionSync(
|
|
13581
|
+
this.cacheKey
|
|
13582
|
+
);
|
|
13583
|
+
if (cachedSolution) {
|
|
13584
|
+
this.applyCachedSolution(
|
|
13585
|
+
cachedSolution
|
|
13586
|
+
);
|
|
13587
|
+
return true;
|
|
13588
|
+
}
|
|
13589
|
+
} catch (error) {
|
|
13590
|
+
console.error("Error attempting to use cache:", error);
|
|
13591
|
+
}
|
|
13592
|
+
return false;
|
|
13593
|
+
}
|
|
13594
|
+
saveToCacheSync() {
|
|
13595
|
+
if (!this.cacheKey) {
|
|
13596
|
+
console.error("Cannot save to cache without cache key.");
|
|
13597
|
+
return;
|
|
13598
|
+
}
|
|
13599
|
+
if (!this.cacheToSolveSpaceTransform) {
|
|
13600
|
+
console.error(
|
|
13601
|
+
"Cache transform not available, cannot save solution to cache."
|
|
13602
|
+
);
|
|
13603
|
+
return;
|
|
13604
|
+
}
|
|
13605
|
+
let cachedSolution;
|
|
13606
|
+
if (this.failed) {
|
|
13607
|
+
cachedSolution = { success: false };
|
|
13608
|
+
} else if (this.solved) {
|
|
13609
|
+
const solutionPathsInCacheSpace = {};
|
|
13610
|
+
const { cacheSpaceToRealNodeId, cacheSpaceToRealConnectionId } = this.cacheToSolveSpaceTransform;
|
|
13611
|
+
const realToCacheSpaceNodeId = /* @__PURE__ */ new Map();
|
|
13612
|
+
for (const [cacheId, realId] of cacheSpaceToRealNodeId) {
|
|
13613
|
+
realToCacheSpaceNodeId.set(realId, cacheId);
|
|
13614
|
+
}
|
|
13615
|
+
const realToCacheSpaceConnectionId = /* @__PURE__ */ new Map();
|
|
13616
|
+
for (const [cacheConnId, realConnName] of cacheSpaceToRealConnectionId) {
|
|
13617
|
+
realToCacheSpaceConnectionId.set(realConnName, cacheConnId);
|
|
13618
|
+
}
|
|
13619
|
+
const realSolutionPaths = [];
|
|
13620
|
+
if (super.sectionConnectionTerminals) {
|
|
13621
|
+
for (const terminal of super.sectionConnectionTerminals) {
|
|
13622
|
+
if (terminal.path && terminal.path.length > 0) {
|
|
13623
|
+
const realPathNodeIds = terminal.path.map(
|
|
13624
|
+
(node) => node.capacityMeshNodeId
|
|
13625
|
+
);
|
|
13626
|
+
realSolutionPaths.push([terminal.connectionName, realPathNodeIds]);
|
|
13627
|
+
}
|
|
13628
|
+
}
|
|
13629
|
+
}
|
|
13630
|
+
for (const [realConnectionName, realPathNodeIds] of realSolutionPaths) {
|
|
13631
|
+
const cacheConnectionId = realToCacheSpaceConnectionId.get(realConnectionName);
|
|
13632
|
+
if (!cacheConnectionId) {
|
|
13633
|
+
console.warn(
|
|
13634
|
+
`Could not find cache space connection ID for ${realConnectionName} when saving to cache.`
|
|
13635
|
+
);
|
|
13636
|
+
continue;
|
|
13637
|
+
}
|
|
13638
|
+
const cachePathNodeIds = realPathNodeIds.map((realNodeId) => {
|
|
13639
|
+
const cacheNodeId = realToCacheSpaceNodeId.get(realNodeId);
|
|
13640
|
+
if (!cacheNodeId) {
|
|
13641
|
+
throw new Error(
|
|
13642
|
+
`Could not map real node ID ${realNodeId} to cache node ID for connection ${realConnectionName} when saving to cache.`
|
|
13643
|
+
);
|
|
13644
|
+
}
|
|
13645
|
+
return cacheNodeId;
|
|
13646
|
+
});
|
|
13647
|
+
solutionPathsInCacheSpace[cacheConnectionId] = cachePathNodeIds;
|
|
13648
|
+
}
|
|
13649
|
+
cachedSolution = {
|
|
13650
|
+
success: true,
|
|
13651
|
+
sectionScore: this.sectionScore,
|
|
13652
|
+
solutionPaths: solutionPathsInCacheSpace
|
|
13653
|
+
};
|
|
13654
|
+
} else {
|
|
13655
|
+
return;
|
|
13656
|
+
}
|
|
13657
|
+
try {
|
|
13658
|
+
this.cacheProvider?.setCachedSolutionSync(this.cacheKey, cachedSolution);
|
|
13659
|
+
} catch (error) {
|
|
13660
|
+
console.error("Error saving solution to cache:", error);
|
|
13661
|
+
}
|
|
13662
|
+
}
|
|
13663
|
+
get sectionConnectionTerminals() {
|
|
13664
|
+
if (this.cacheHit && this.solved && this.cachedSectionConnectionTerminals) {
|
|
13665
|
+
console.log("returning the cached section connection terminals");
|
|
13666
|
+
return this.cachedSectionConnectionTerminals;
|
|
13667
|
+
}
|
|
13668
|
+
return super.sectionConnectionTerminals;
|
|
13669
|
+
}
|
|
13670
|
+
visualize() {
|
|
13671
|
+
if (!this.cacheHit) return super.visualize();
|
|
13672
|
+
const graphics = visualizeSection({
|
|
13673
|
+
sectionNodes: this.constructorParams.sectionNodes,
|
|
13674
|
+
sectionEdges: this.constructorParams.sectionEdges,
|
|
13675
|
+
sectionConnectionTerminals: this.cachedSectionConnectionTerminals,
|
|
13676
|
+
completedPaths: this.cachedSectionConnectionTerminals.map((t) => ({
|
|
13677
|
+
connectionName: t.connectionName,
|
|
13678
|
+
path: t.path
|
|
13679
|
+
})),
|
|
13680
|
+
nodeMap: this.constructorParams.nodeMap,
|
|
13681
|
+
colorMap: this.constructorParams.colorMap,
|
|
13682
|
+
title: "CachedHyperCapacityPathingSingleSectionSolver"
|
|
13683
|
+
});
|
|
13684
|
+
return graphics;
|
|
13214
13685
|
}
|
|
13215
|
-
return {
|
|
13216
|
-
sectionConnectionTerminals,
|
|
13217
|
-
sectionNodes,
|
|
13218
|
-
sectionEdges,
|
|
13219
|
-
centerNodeId
|
|
13220
|
-
};
|
|
13221
13686
|
};
|
|
13222
13687
|
|
|
13223
13688
|
// lib/solvers/CapacityPathingSectionSolver/CapacityPathingMultiSectionSolver.ts
|
|
@@ -13230,8 +13695,10 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13230
13695
|
// Initialize here
|
|
13231
13696
|
colorMap;
|
|
13232
13697
|
initialSolver;
|
|
13698
|
+
cacheProvider;
|
|
13233
13699
|
stage = "initialization";
|
|
13234
13700
|
nodeMap = /* @__PURE__ */ new Map();
|
|
13701
|
+
allNodeIdsSet;
|
|
13235
13702
|
usedNodeCapacityMap = /* @__PURE__ */ new Map();
|
|
13236
13703
|
totalNodeCapacityMap = /* @__PURE__ */ new Map();
|
|
13237
13704
|
// Added
|
|
@@ -13241,6 +13708,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13241
13708
|
sectionSolver = null;
|
|
13242
13709
|
currentScheduleIndex = 0;
|
|
13243
13710
|
stats;
|
|
13711
|
+
// Adjusting this schedule is a trade-off between optimization speed and quality.
|
|
13244
13712
|
OPTIMIZATION_SCHEDULE = [
|
|
13245
13713
|
{
|
|
13246
13714
|
MAX_ATTEMPTS_PER_NODE: 1,
|
|
@@ -13255,7 +13723,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13255
13723
|
{
|
|
13256
13724
|
MAX_ATTEMPTS_PER_NODE: 3,
|
|
13257
13725
|
MAX_EXPANSION_DEGREES: 7,
|
|
13258
|
-
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: 0.
|
|
13726
|
+
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: 0.9
|
|
13259
13727
|
}
|
|
13260
13728
|
];
|
|
13261
13729
|
get currentSchedule() {
|
|
@@ -13267,6 +13735,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13267
13735
|
successfulOptimizations: 0,
|
|
13268
13736
|
failedOptimizations: 0,
|
|
13269
13737
|
failedSectionSolvers: 0,
|
|
13738
|
+
startingScore: 0,
|
|
13270
13739
|
scheduleScores: this.OPTIMIZATION_SCHEDULE.map(
|
|
13271
13740
|
({ MAX_EXPANSION_DEGREES }) => ({
|
|
13272
13741
|
maxExpansionDegrees: MAX_EXPANSION_DEGREES,
|
|
@@ -13277,6 +13746,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13277
13746
|
)
|
|
13278
13747
|
};
|
|
13279
13748
|
this.MAX_ITERATIONS = 1e7;
|
|
13749
|
+
this.cacheProvider = params.cacheProvider;
|
|
13280
13750
|
this.simpleRouteJson = params.simpleRouteJson;
|
|
13281
13751
|
this.nodes = params.nodes;
|
|
13282
13752
|
this.edges = params.edges;
|
|
@@ -13297,6 +13767,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13297
13767
|
const totalCapacity = this.initialSolver.getTotalCapacity(node);
|
|
13298
13768
|
this.totalNodeCapacityMap.set(node.capacityMeshNodeId, totalCapacity);
|
|
13299
13769
|
}
|
|
13770
|
+
this.allNodeIdsSet = new Set(this.nodes.map((n) => n.capacityMeshNodeId));
|
|
13300
13771
|
}
|
|
13301
13772
|
_stepInitialization() {
|
|
13302
13773
|
this.initialSolver?.step();
|
|
@@ -13315,6 +13786,12 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13315
13786
|
this.nodeOptimizationAttemptCountMap.set(node.capacityMeshNodeId, 0);
|
|
13316
13787
|
}
|
|
13317
13788
|
this.connectionsWithNodes = this.initialSolver.connectionsWithNodes;
|
|
13789
|
+
this.stats.startingScore = computeSectionScore({
|
|
13790
|
+
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
13791
|
+
usedNodeCapacityMap: this.usedNodeCapacityMap,
|
|
13792
|
+
nodeMap: this.nodeMap,
|
|
13793
|
+
sectionNodeIds: this.allNodeIdsSet
|
|
13794
|
+
});
|
|
13318
13795
|
this.stage = "section-optimization";
|
|
13319
13796
|
}
|
|
13320
13797
|
}
|
|
@@ -13366,9 +13843,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13366
13843
|
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
13367
13844
|
usedNodeCapacityMap: this.usedNodeCapacityMap,
|
|
13368
13845
|
nodeMap: this.nodeMap,
|
|
13369
|
-
sectionNodeIds:
|
|
13370
|
-
this.nodes.map((node) => node.capacityMeshNodeId)
|
|
13371
|
-
)
|
|
13846
|
+
sectionNodeIds: this.allNodeIdsSet
|
|
13372
13847
|
})
|
|
13373
13848
|
};
|
|
13374
13849
|
}
|
|
@@ -13396,13 +13871,17 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13396
13871
|
});
|
|
13397
13872
|
this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++;
|
|
13398
13873
|
this.currentSection = section;
|
|
13399
|
-
this.sectionSolver = new
|
|
13874
|
+
this.sectionSolver = new CachedHyperCapacityPathingSingleSectionSolver({
|
|
13400
13875
|
sectionNodes: this.currentSection.sectionNodes,
|
|
13401
13876
|
sectionEdges: this.currentSection.sectionEdges,
|
|
13402
13877
|
sectionConnectionTerminals: this.currentSection.sectionConnectionTerminals,
|
|
13403
13878
|
colorMap: this.colorMap,
|
|
13404
13879
|
centerNodeId: this.currentSection.centerNodeId,
|
|
13405
|
-
nodeEdgeMap: this.nodeEdgeMap
|
|
13880
|
+
nodeEdgeMap: this.nodeEdgeMap,
|
|
13881
|
+
hyperParameters: {
|
|
13882
|
+
EXPANSION_DEGREES: this.currentSchedule.MAX_EXPANSION_DEGREES
|
|
13883
|
+
},
|
|
13884
|
+
cacheProvider: this.cacheProvider
|
|
13406
13885
|
});
|
|
13407
13886
|
this.activeSubSolver = this.sectionSolver;
|
|
13408
13887
|
this.nodeOptimizationAttemptCountMap.set(
|
|
@@ -13422,18 +13901,19 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13422
13901
|
return;
|
|
13423
13902
|
}
|
|
13424
13903
|
if (this.sectionSolver.solved) {
|
|
13425
|
-
const
|
|
13426
|
-
const
|
|
13904
|
+
const sectionConnectionTerminals = this.sectionSolver.sectionConnectionTerminals;
|
|
13905
|
+
const sectionNodes = this.sectionSolver.sectionNodes;
|
|
13906
|
+
const centerNodeId = this.sectionSolver.centerNodeId;
|
|
13427
13907
|
this.sectionSolver = null;
|
|
13428
13908
|
this.activeSubSolver = null;
|
|
13429
|
-
if (!
|
|
13909
|
+
if (!sectionConnectionTerminals) {
|
|
13430
13910
|
console.warn(
|
|
13431
13911
|
`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`
|
|
13432
13912
|
);
|
|
13433
13913
|
return;
|
|
13434
13914
|
}
|
|
13435
13915
|
const sectionNodeIds = new Set(
|
|
13436
|
-
|
|
13916
|
+
sectionNodes.map((n) => n.capacityMeshNodeId)
|
|
13437
13917
|
);
|
|
13438
13918
|
const beforeScore = computeSectionScore({
|
|
13439
13919
|
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
@@ -13442,7 +13922,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13442
13922
|
sectionNodeIds
|
|
13443
13923
|
});
|
|
13444
13924
|
const afterUsedCapacityMap = new Map(this.usedNodeCapacityMap);
|
|
13445
|
-
const newSectionPaths =
|
|
13925
|
+
const newSectionPaths = sectionConnectionTerminals;
|
|
13446
13926
|
for (const terminal of newSectionPaths) {
|
|
13447
13927
|
const originalConnection = this.connectionsWithNodes.find(
|
|
13448
13928
|
(conn) => conn.connection.name === terminal.connectionName
|
|
@@ -13479,7 +13959,10 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13479
13959
|
});
|
|
13480
13960
|
if (afterScore > beforeScore) {
|
|
13481
13961
|
this.stats.successfulOptimizations++;
|
|
13482
|
-
this._mergeSolvedSectionPaths(
|
|
13962
|
+
this._mergeSolvedSectionPaths({
|
|
13963
|
+
centerNodeId,
|
|
13964
|
+
sectionConnectionTerminals
|
|
13965
|
+
});
|
|
13483
13966
|
this._recalculateNodeCapacityUsage();
|
|
13484
13967
|
} else {
|
|
13485
13968
|
this.stats.failedOptimizations++;
|
|
@@ -13490,16 +13973,11 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13490
13973
|
* Merges the paths found by a successful section solver back into the main
|
|
13491
13974
|
* connectionsWithNodes list.
|
|
13492
13975
|
*/
|
|
13493
|
-
_mergeSolvedSectionPaths(
|
|
13494
|
-
|
|
13495
|
-
|
|
13496
|
-
|
|
13497
|
-
|
|
13498
|
-
);
|
|
13499
|
-
return;
|
|
13500
|
-
}
|
|
13501
|
-
const solvedTerminals = solvedSectionSolver.sectionConnectionTerminals;
|
|
13502
|
-
for (const solvedTerminal of solvedTerminals) {
|
|
13976
|
+
_mergeSolvedSectionPaths({
|
|
13977
|
+
centerNodeId,
|
|
13978
|
+
sectionConnectionTerminals
|
|
13979
|
+
}) {
|
|
13980
|
+
for (const solvedTerminal of sectionConnectionTerminals) {
|
|
13503
13981
|
if (!solvedTerminal.path) {
|
|
13504
13982
|
console.warn(
|
|
13505
13983
|
`No path found for connection ${solvedTerminal.connectionName} in section ${centerNodeId}`
|
|
@@ -13511,7 +13989,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13511
13989
|
);
|
|
13512
13990
|
if (!originalConnection || !originalConnection.path) {
|
|
13513
13991
|
console.warn(
|
|
13514
|
-
`Original connection or path not found for ${solvedTerminal.connectionName} while merging section ${
|
|
13992
|
+
`Original connection or path not found for ${solvedTerminal.connectionName} while merging section ${centerNodeId}`
|
|
13515
13993
|
);
|
|
13516
13994
|
continue;
|
|
13517
13995
|
}
|
|
@@ -15858,7 +16336,7 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
15858
16336
|
}
|
|
15859
16337
|
this.connMap = getConnectivityMapFromSimpleRouteJson(srj);
|
|
15860
16338
|
this.colorMap = getColorMap(srj, this.connMap);
|
|
15861
|
-
this.cacheProvider = opts.cacheProvider
|
|
16339
|
+
this.cacheProvider = opts.cacheProvider === void 0 ? getGlobalInMemoryCache() : opts.cacheProvider === null ? null : opts.cacheProvider;
|
|
15862
16340
|
this.startTimeOfPhase = {};
|
|
15863
16341
|
this.endTimeOfPhase = {};
|
|
15864
16342
|
this.timeSpentOnPhase = {};
|
|
@@ -15982,6 +16460,7 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
15982
16460
|
nodes: cms.capacityNodes,
|
|
15983
16461
|
edges: cms.edgeSolver?.edges || [],
|
|
15984
16462
|
colorMap: cms.colorMap,
|
|
16463
|
+
cacheProvider: cms.cacheProvider,
|
|
15985
16464
|
hyperParameters: {
|
|
15986
16465
|
MAX_CAPACITY_FACTOR: 1
|
|
15987
16466
|
}
|
|
@@ -16324,7 +16803,12 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
16324
16803
|
var CapacityMeshSolver = AutoroutingPipelineSolver;
|
|
16325
16804
|
export {
|
|
16326
16805
|
CapacityMeshSolver,
|
|
16806
|
+
InMemoryCache,
|
|
16807
|
+
LocalStorageCache,
|
|
16327
16808
|
calculateOptimalCapacityDepth,
|
|
16328
|
-
|
|
16809
|
+
getGlobalInMemoryCache,
|
|
16810
|
+
getGlobalLocalStorageCache,
|
|
16811
|
+
getTunedTotalCapacity1,
|
|
16812
|
+
setupGlobalCaches
|
|
16329
16813
|
};
|
|
16330
16814
|
//# sourceMappingURL=index.js.map
|