@tscircuit/capacity-autorouter 0.0.61 → 0.0.63
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 +136 -1
- package/dist/index.js +602 -141
- 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++) {
|
|
@@ -3897,7 +3943,12 @@ var IntraNodeRouteSolver = class extends BaseSolver {
|
|
|
3897
3943
|
y: points[points.length - 1].y,
|
|
3898
3944
|
z: points[points.length - 1].z
|
|
3899
3945
|
},
|
|
3900
|
-
obstacleRoutes: this.solvedRoutes
|
|
3946
|
+
obstacleRoutes: this.connMap ? this.solvedRoutes.filter(
|
|
3947
|
+
(sr) => !this.connMap.areIdsConnected(
|
|
3948
|
+
sr.connectionName,
|
|
3949
|
+
connectionName
|
|
3950
|
+
)
|
|
3951
|
+
) : this.solvedRoutes,
|
|
3901
3952
|
futureConnections: this.unsolvedConnections,
|
|
3902
3953
|
layerCount: 2,
|
|
3903
3954
|
hyperParameters: this.hyperParameters,
|
|
@@ -8837,9 +8888,11 @@ var HyperSingleIntraNodeSolver = class extends HyperParameterSupervisorSolver {
|
|
|
8837
8888
|
constructorParams;
|
|
8838
8889
|
solvedRoutes = [];
|
|
8839
8890
|
nodeWithPortPoints;
|
|
8891
|
+
connMap;
|
|
8840
8892
|
constructor(opts) {
|
|
8841
8893
|
super();
|
|
8842
8894
|
this.nodeWithPortPoints = opts.nodeWithPortPoints;
|
|
8895
|
+
this.connMap = opts.connMap;
|
|
8843
8896
|
this.constructorParams = opts;
|
|
8844
8897
|
this.MAX_ITERATIONS = 25e4;
|
|
8845
8898
|
this.GREEDY_MULTIPLIER = 5;
|
|
@@ -8983,6 +9036,7 @@ var HyperSingleIntraNodeSolver = class extends HyperParameterSupervisorSolver {
|
|
|
8983
9036
|
if (hyperParameters.MULTI_HEAD_POLYLINE_SOLVER) {
|
|
8984
9037
|
return new MultiHeadPolyLineIntraNodeSolver3({
|
|
8985
9038
|
nodeWithPortPoints: this.nodeWithPortPoints,
|
|
9039
|
+
connMap: this.connMap,
|
|
8986
9040
|
hyperParameters
|
|
8987
9041
|
});
|
|
8988
9042
|
}
|
|
@@ -9071,7 +9125,7 @@ var HighDensitySolver = class extends BaseSolver {
|
|
|
9071
9125
|
if (this.failedSolvers.length > 0) {
|
|
9072
9126
|
this.solved = false;
|
|
9073
9127
|
this.failed = true;
|
|
9074
|
-
this.error = `Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0, 5).map((fs) => fs.nodeWithPortPoints.capacityMeshNodeId)}
|
|
9128
|
+
this.error = `Failed to solve ${this.failedSolvers.length} nodes, ${this.failedSolvers.slice(0, 5).map((fs) => fs.nodeWithPortPoints.capacityMeshNodeId)}. err0: ${this.failedSolvers[0].error}.`;
|
|
9075
9129
|
return;
|
|
9076
9130
|
}
|
|
9077
9131
|
this.solved = true;
|
|
@@ -10929,6 +10983,8 @@ import objectHash from "object-hash";
|
|
|
10929
10983
|
|
|
10930
10984
|
// lib/cache/InMemoryCache.ts
|
|
10931
10985
|
var InMemoryCache = class {
|
|
10986
|
+
cacheHitsByPrefix = {};
|
|
10987
|
+
cacheMissesByPrefix = {};
|
|
10932
10988
|
isSyncCache = true;
|
|
10933
10989
|
cacheHits = 0;
|
|
10934
10990
|
cacheMisses = 0;
|
|
@@ -10994,6 +11050,8 @@ var LocalStorageCache = class {
|
|
|
10994
11050
|
isSyncCache = true;
|
|
10995
11051
|
cacheHits = 0;
|
|
10996
11052
|
cacheMisses = 0;
|
|
11053
|
+
cacheHitsByPrefix = {};
|
|
11054
|
+
cacheMissesByPrefix = {};
|
|
10997
11055
|
constructor() {
|
|
10998
11056
|
if (typeof localStorage === "undefined") {
|
|
10999
11057
|
console.warn(
|
|
@@ -11018,14 +11076,20 @@ var LocalStorageCache = class {
|
|
|
11018
11076
|
if (cachedItem !== null) {
|
|
11019
11077
|
const solution = JSON.parse(cachedItem);
|
|
11020
11078
|
this.cacheHits++;
|
|
11079
|
+
const prefix = cacheKey.split(":")[0];
|
|
11080
|
+
this.cacheHitsByPrefix[prefix] = (this.cacheHitsByPrefix[prefix] || 0) + 1;
|
|
11021
11081
|
return solution;
|
|
11022
11082
|
} else {
|
|
11023
11083
|
this.cacheMisses++;
|
|
11084
|
+
const prefix = cacheKey.split(":")[0];
|
|
11085
|
+
this.cacheMissesByPrefix[prefix] = (this.cacheMissesByPrefix[prefix] || 0) + 1;
|
|
11024
11086
|
return void 0;
|
|
11025
11087
|
}
|
|
11026
11088
|
} catch (error) {
|
|
11027
11089
|
console.error(`Error getting cached solution sync for ${key}:`, error);
|
|
11028
11090
|
this.cacheMisses++;
|
|
11091
|
+
const prefix = cacheKey.split(":")[0];
|
|
11092
|
+
this.cacheMissesByPrefix[prefix] = (this.cacheMissesByPrefix[prefix] || 0) + 1;
|
|
11029
11093
|
return void 0;
|
|
11030
11094
|
}
|
|
11031
11095
|
}
|
|
@@ -11090,6 +11154,8 @@ var LocalStorageCache = class {
|
|
|
11090
11154
|
} finally {
|
|
11091
11155
|
this.cacheHits = 0;
|
|
11092
11156
|
this.cacheMisses = 0;
|
|
11157
|
+
this.cacheHitsByPrefix = {};
|
|
11158
|
+
this.cacheMissesByPrefix = {};
|
|
11093
11159
|
}
|
|
11094
11160
|
}
|
|
11095
11161
|
getAllCacheKeys() {
|
|
@@ -11111,6 +11177,12 @@ function getGlobalLocalStorageCache() {
|
|
|
11111
11177
|
}
|
|
11112
11178
|
return globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE;
|
|
11113
11179
|
}
|
|
11180
|
+
function getGlobalInMemoryCache() {
|
|
11181
|
+
if (!globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE) {
|
|
11182
|
+
setupGlobalCaches();
|
|
11183
|
+
}
|
|
11184
|
+
return globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE;
|
|
11185
|
+
}
|
|
11114
11186
|
function setupGlobalCaches() {
|
|
11115
11187
|
globalThis.TSCIRCUIT_AUTOROUTER_LOCAL_STORAGE_CACHE ??= new LocalStorageCache();
|
|
11116
11188
|
globalThis.TSCIRCUIT_AUTOROUTER_IN_MEMORY_CACHE ??= new InMemoryCache();
|
|
@@ -12513,6 +12585,21 @@ var calculateNodeProbabilityOfFailure2 = (usedCapacity, totalCapacity, layerCoun
|
|
|
12513
12585
|
const adjustedRatio = ratioOverTotal - 1;
|
|
12514
12586
|
return 1 - Math.exp(-k * adjustedRatio);
|
|
12515
12587
|
};
|
|
12588
|
+
var calculateSingleNodeLogSuccessProbability = (usedCapacity, totalCapacity, node) => {
|
|
12589
|
+
if (node._containsTarget) return 0;
|
|
12590
|
+
if (usedCapacity <= totalCapacity) return 0;
|
|
12591
|
+
const probabilityOfFailure = calculateNodeProbabilityOfFailure2(
|
|
12592
|
+
usedCapacity,
|
|
12593
|
+
totalCapacity,
|
|
12594
|
+
node.availableZ.length
|
|
12595
|
+
);
|
|
12596
|
+
const probabilityOfSuccess = 1 - probabilityOfFailure;
|
|
12597
|
+
if (probabilityOfSuccess <= 0) {
|
|
12598
|
+
return -1e9;
|
|
12599
|
+
} else {
|
|
12600
|
+
return Math.log(probabilityOfSuccess);
|
|
12601
|
+
}
|
|
12602
|
+
};
|
|
12516
12603
|
var computeSectionScore = ({
|
|
12517
12604
|
totalNodeCapacityMap,
|
|
12518
12605
|
usedNodeCapacityMap,
|
|
@@ -12526,21 +12613,13 @@ var computeSectionScore = ({
|
|
|
12526
12613
|
if (!totalNodeCapacityMap.has(nodeId)) continue;
|
|
12527
12614
|
const node = nodeMap.get(nodeId);
|
|
12528
12615
|
if (!node) continue;
|
|
12529
|
-
if (node._containsTarget) continue;
|
|
12530
12616
|
const totalCapacity = totalNodeCapacityMap.get(nodeId);
|
|
12531
12617
|
const usedCapacity = usedNodeCapacityMap.get(nodeId) ?? 0;
|
|
12532
|
-
|
|
12533
|
-
const probabilityOfFailure = calculateNodeProbabilityOfFailure2(
|
|
12618
|
+
logProbabilityOfSuccessSum += calculateSingleNodeLogSuccessProbability(
|
|
12534
12619
|
usedCapacity,
|
|
12535
12620
|
totalCapacity,
|
|
12536
|
-
node
|
|
12621
|
+
node
|
|
12537
12622
|
);
|
|
12538
|
-
const probabilityOfSuccess = 1 - probabilityOfFailure;
|
|
12539
|
-
if (probabilityOfSuccess <= 0) {
|
|
12540
|
-
logProbabilityOfSuccessSum += -1e9;
|
|
12541
|
-
} else {
|
|
12542
|
-
logProbabilityOfSuccessSum += Math.log(probabilityOfSuccess);
|
|
12543
|
-
}
|
|
12544
12623
|
}
|
|
12545
12624
|
return logProbabilityOfSuccessSum;
|
|
12546
12625
|
};
|
|
@@ -12721,9 +12800,9 @@ ${percent}% (Pf: ${(probabilityOfFailure * 100).toFixed(1)}%)`;
|
|
|
12721
12800
|
x: x + offset.x,
|
|
12722
12801
|
y: y + offset.y
|
|
12723
12802
|
})),
|
|
12724
|
-
strokeColor: safeTransparentize(pathColor, 0.2)
|
|
12803
|
+
strokeColor: safeTransparentize(pathColor, 0.2)
|
|
12725
12804
|
// Make solved paths semi-transparent
|
|
12726
|
-
strokeWidth: 0.03
|
|
12805
|
+
// strokeWidth: 0.03,
|
|
12727
12806
|
});
|
|
12728
12807
|
}
|
|
12729
12808
|
});
|
|
@@ -12731,6 +12810,72 @@ ${percent}% (Pf: ${(probabilityOfFailure * 100).toFixed(1)}%)`;
|
|
|
12731
12810
|
return graphics;
|
|
12732
12811
|
}
|
|
12733
12812
|
|
|
12813
|
+
// lib/solvers/CapacityPathingSectionSolver/computeSectionNodesTerminalsAndEdges.ts
|
|
12814
|
+
var computeSectionNodesTerminalsAndEdges = (opts) => {
|
|
12815
|
+
const {
|
|
12816
|
+
centerNodeId,
|
|
12817
|
+
connectionsWithNodes,
|
|
12818
|
+
nodeMap,
|
|
12819
|
+
edges,
|
|
12820
|
+
nodeEdgeMap,
|
|
12821
|
+
expansionDegrees
|
|
12822
|
+
} = opts;
|
|
12823
|
+
const sectionNodeIds = /* @__PURE__ */ new Set();
|
|
12824
|
+
const queue = [
|
|
12825
|
+
{ nodeId: centerNodeId, depth: 0 }
|
|
12826
|
+
];
|
|
12827
|
+
sectionNodeIds.add(centerNodeId);
|
|
12828
|
+
let head = 0;
|
|
12829
|
+
while (head < queue.length) {
|
|
12830
|
+
const { nodeId, depth } = queue[head++];
|
|
12831
|
+
if (depth >= expansionDegrees) continue;
|
|
12832
|
+
const neighbors = nodeEdgeMap.get(nodeId)?.flatMap((edge) => edge.nodeIds.filter((id) => id !== nodeId)) ?? [];
|
|
12833
|
+
for (const neighborId of neighbors) {
|
|
12834
|
+
if (!sectionNodeIds.has(neighborId)) {
|
|
12835
|
+
sectionNodeIds.add(neighborId);
|
|
12836
|
+
queue.push({ nodeId: neighborId, depth: depth + 1 });
|
|
12837
|
+
}
|
|
12838
|
+
}
|
|
12839
|
+
}
|
|
12840
|
+
const sectionNodes = Array.from(sectionNodeIds).map((id) => nodeMap.get(id));
|
|
12841
|
+
const sectionEdges = edges.filter((edge) => {
|
|
12842
|
+
const [nodeIdA, nodeIdB] = edge.nodeIds;
|
|
12843
|
+
return sectionNodeIds.has(nodeIdA) && sectionNodeIds.has(nodeIdB);
|
|
12844
|
+
});
|
|
12845
|
+
const sectionConnectionTerminals = [];
|
|
12846
|
+
for (const conn of connectionsWithNodes) {
|
|
12847
|
+
if (!conn.path) continue;
|
|
12848
|
+
let startNodeId = null;
|
|
12849
|
+
let endNodeId = null;
|
|
12850
|
+
for (const node of conn.path) {
|
|
12851
|
+
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
12852
|
+
startNodeId = node.capacityMeshNodeId;
|
|
12853
|
+
break;
|
|
12854
|
+
}
|
|
12855
|
+
}
|
|
12856
|
+
for (let i = conn.path.length - 1; i >= 0; i--) {
|
|
12857
|
+
const node = conn.path[i];
|
|
12858
|
+
if (sectionNodeIds.has(node.capacityMeshNodeId)) {
|
|
12859
|
+
endNodeId = node.capacityMeshNodeId;
|
|
12860
|
+
break;
|
|
12861
|
+
}
|
|
12862
|
+
}
|
|
12863
|
+
if (startNodeId && endNodeId) {
|
|
12864
|
+
sectionConnectionTerminals.push({
|
|
12865
|
+
connectionName: conn.connection.name,
|
|
12866
|
+
startNodeId,
|
|
12867
|
+
endNodeId
|
|
12868
|
+
});
|
|
12869
|
+
}
|
|
12870
|
+
}
|
|
12871
|
+
return {
|
|
12872
|
+
sectionConnectionTerminals,
|
|
12873
|
+
sectionNodes,
|
|
12874
|
+
sectionEdges,
|
|
12875
|
+
centerNodeId
|
|
12876
|
+
};
|
|
12877
|
+
};
|
|
12878
|
+
|
|
12734
12879
|
// lib/solvers/CapacityPathingSectionSolver/CapacityPathingSingleSectionSolver.ts
|
|
12735
12880
|
var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
12736
12881
|
GREEDY_MULTIPLIER = 1.5;
|
|
@@ -12744,7 +12889,10 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
12744
12889
|
colorMap;
|
|
12745
12890
|
usedNodeCapacityMap;
|
|
12746
12891
|
// Tracks capacity usage *within this solver's run*
|
|
12892
|
+
totalNodeCapacityMap;
|
|
12893
|
+
// Added: Stores total capacity for each node
|
|
12747
12894
|
centerNodeId;
|
|
12895
|
+
currentSectionScore = 0;
|
|
12748
12896
|
MAX_CANDIDATES_IN_MEMORY = 1e4;
|
|
12749
12897
|
// A* state
|
|
12750
12898
|
currentConnectionIndex = 0;
|
|
@@ -12765,14 +12913,28 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
12765
12913
|
this.sectionConnectionTerminals = params.sectionConnectionTerminals.map(
|
|
12766
12914
|
(t) => ({ ...t, path: void 0 })
|
|
12767
12915
|
);
|
|
12768
|
-
this.nodeMap = new Map(
|
|
12769
|
-
this.sectionNodes.map((n) => [n.capacityMeshNodeId, n])
|
|
12770
|
-
);
|
|
12916
|
+
this.nodeMap = params.nodeMap ?? new Map(this.sectionNodes.map((n) => [n.capacityMeshNodeId, n]));
|
|
12771
12917
|
this.nodeEdgeMap = params.nodeEdgeMap ?? getNodeEdgeMap(this.sectionEdges);
|
|
12772
12918
|
this.colorMap = params.colorMap ?? {};
|
|
12773
12919
|
this.usedNodeCapacityMap = new Map(
|
|
12774
12920
|
this.sectionNodes.map((node) => [node.capacityMeshNodeId, 0])
|
|
12775
12921
|
);
|
|
12922
|
+
this.totalNodeCapacityMap = new Map(
|
|
12923
|
+
this.sectionNodes.map((node) => [
|
|
12924
|
+
node.capacityMeshNodeId,
|
|
12925
|
+
this.getTotalCapacity(node)
|
|
12926
|
+
])
|
|
12927
|
+
);
|
|
12928
|
+
const initialSectionNodeIds = new Set(
|
|
12929
|
+
this.sectionNodes.map((n) => n.capacityMeshNodeId)
|
|
12930
|
+
);
|
|
12931
|
+
this.currentSectionScore = computeSectionScore({
|
|
12932
|
+
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
12933
|
+
usedNodeCapacityMap: this.usedNodeCapacityMap,
|
|
12934
|
+
// Reflects initial capacities
|
|
12935
|
+
nodeMap: this.nodeMap,
|
|
12936
|
+
sectionNodeIds: initialSectionNodeIds
|
|
12937
|
+
});
|
|
12776
12938
|
if (params.hyperParameters?.SHUFFLE_SEED) {
|
|
12777
12939
|
this.sectionConnectionTerminals = cloneAndShuffleArray(
|
|
12778
12940
|
this.sectionConnectionTerminals,
|
|
@@ -12852,15 +13014,40 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
12852
13014
|
}
|
|
12853
13015
|
// Adapted from CapacityPathingSolver - uses section's capacity map
|
|
12854
13016
|
reduceCapacityAlongPath(path) {
|
|
12855
|
-
for (const
|
|
12856
|
-
if (this.usedNodeCapacityMap.has(
|
|
12857
|
-
|
|
12858
|
-
|
|
12859
|
-
|
|
13017
|
+
for (const pathNode of path) {
|
|
13018
|
+
if (this.usedNodeCapacityMap.has(pathNode.capacityMeshNodeId)) {
|
|
13019
|
+
const nodeId = pathNode.capacityMeshNodeId;
|
|
13020
|
+
const nodeInSection = this.nodeMap.get(nodeId);
|
|
13021
|
+
if (!nodeInSection) {
|
|
13022
|
+
console.warn(
|
|
13023
|
+
`Node ${nodeId} from path not found in section's nodeMap during score update.`
|
|
13024
|
+
);
|
|
13025
|
+
continue;
|
|
13026
|
+
}
|
|
13027
|
+
const totalCapacity = this.totalNodeCapacityMap.get(nodeId);
|
|
13028
|
+
const oldUsedCapacity = this.usedNodeCapacityMap.get(nodeId) ?? 0;
|
|
13029
|
+
const oldNodeScoreContribution = calculateSingleNodeLogSuccessProbability(
|
|
13030
|
+
oldUsedCapacity,
|
|
13031
|
+
totalCapacity,
|
|
13032
|
+
nodeInSection
|
|
13033
|
+
// Use the node object from the section's map
|
|
12860
13034
|
);
|
|
13035
|
+
this.currentSectionScore -= oldNodeScoreContribution;
|
|
13036
|
+
const newUsedCapacity = oldUsedCapacity + 1;
|
|
13037
|
+
this.usedNodeCapacityMap.set(nodeId, newUsedCapacity);
|
|
13038
|
+
const newNodeScoreContribution = calculateSingleNodeLogSuccessProbability(
|
|
13039
|
+
newUsedCapacity,
|
|
13040
|
+
totalCapacity,
|
|
13041
|
+
nodeInSection
|
|
13042
|
+
// Use the node object from the section's map
|
|
13043
|
+
);
|
|
13044
|
+
this.currentSectionScore += newNodeScoreContribution;
|
|
12861
13045
|
}
|
|
12862
13046
|
}
|
|
12863
13047
|
}
|
|
13048
|
+
getSolvedSectionScore() {
|
|
13049
|
+
return this.currentSectionScore;
|
|
13050
|
+
}
|
|
12864
13051
|
_step() {
|
|
12865
13052
|
const currentTerminal = this.sectionConnectionTerminals[this.currentConnectionIndex];
|
|
12866
13053
|
if (!currentTerminal) {
|
|
@@ -13062,6 +13249,7 @@ var CapacityPathingSingleSectionSolver = class extends BaseSolver {
|
|
|
13062
13249
|
var CapacityPathingSingleSectionPathingSolver = CapacityPathingSingleSectionSolver;
|
|
13063
13250
|
|
|
13064
13251
|
// lib/solvers/CapacityPathingSectionSolver/HyperCapacityPathingSingleSectionSolver.ts
|
|
13252
|
+
var range = (n) => Array.from({ length: n }, (_, i) => i);
|
|
13065
13253
|
var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSupervisorSolver {
|
|
13066
13254
|
constructorParams;
|
|
13067
13255
|
winningSolver;
|
|
@@ -13070,14 +13258,24 @@ var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSuperv
|
|
|
13070
13258
|
this.MAX_ITERATIONS = 1e5;
|
|
13071
13259
|
this.constructorParams = params;
|
|
13072
13260
|
}
|
|
13261
|
+
// TODO this needs to use the section score, ideally incorporating the current best candidate
|
|
13262
|
+
// of the paths being explored inside the single section
|
|
13073
13263
|
computeG(solver) {
|
|
13074
|
-
return solver.
|
|
13264
|
+
return -solver.getSolvedSectionScore();
|
|
13075
13265
|
}
|
|
13076
13266
|
computeH(solver) {
|
|
13077
|
-
return
|
|
13267
|
+
return 0;
|
|
13078
13268
|
}
|
|
13079
13269
|
getCombinationDefs() {
|
|
13080
|
-
|
|
13270
|
+
const numConnections = this.constructorParams.sectionConnectionTerminals.length;
|
|
13271
|
+
if (numConnections === 2) {
|
|
13272
|
+
return [["orderings2_for2"]];
|
|
13273
|
+
} else if (numConnections === 3) {
|
|
13274
|
+
return [["orderings6_for3"]];
|
|
13275
|
+
} else if (numConnections === 4) {
|
|
13276
|
+
return [["orderings24_for4"]];
|
|
13277
|
+
}
|
|
13278
|
+
return [["orderings30"]];
|
|
13081
13279
|
}
|
|
13082
13280
|
getFailureMessage() {
|
|
13083
13281
|
return `All CapacityPathingSingleSection solvers failed for "${this.centerNodeId}"`;
|
|
@@ -13085,39 +13283,28 @@ var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSuperv
|
|
|
13085
13283
|
getHyperParameterDefs() {
|
|
13086
13284
|
return [
|
|
13087
13285
|
{
|
|
13088
|
-
name: "
|
|
13089
|
-
possibleValues:
|
|
13090
|
-
|
|
13091
|
-
|
|
13092
|
-
|
|
13093
|
-
|
|
13094
|
-
|
|
13095
|
-
|
|
13096
|
-
|
|
13097
|
-
|
|
13098
|
-
|
|
13099
|
-
|
|
13100
|
-
|
|
13101
|
-
|
|
13102
|
-
|
|
13103
|
-
|
|
13104
|
-
|
|
13105
|
-
|
|
13106
|
-
|
|
13107
|
-
|
|
13108
|
-
|
|
13109
|
-
|
|
13110
|
-
},
|
|
13111
|
-
{
|
|
13112
|
-
SHUFFLE_SEED: 7
|
|
13113
|
-
},
|
|
13114
|
-
{
|
|
13115
|
-
SHUFFLE_SEED: 8
|
|
13116
|
-
},
|
|
13117
|
-
{
|
|
13118
|
-
SHUFFLE_SEED: 9
|
|
13119
|
-
}
|
|
13120
|
-
]
|
|
13286
|
+
name: "orderings2_for2",
|
|
13287
|
+
possibleValues: range(2).map((i) => ({
|
|
13288
|
+
SHUFFLE_SEED: i
|
|
13289
|
+
}))
|
|
13290
|
+
},
|
|
13291
|
+
{
|
|
13292
|
+
name: "orderings6_for3",
|
|
13293
|
+
possibleValues: range(6).map((i) => ({
|
|
13294
|
+
SHUFFLE_SEED: i
|
|
13295
|
+
}))
|
|
13296
|
+
},
|
|
13297
|
+
{
|
|
13298
|
+
name: "orderings24_for4",
|
|
13299
|
+
possibleValues: range(24).map((i) => ({
|
|
13300
|
+
SHUFFLE_SEED: i
|
|
13301
|
+
}))
|
|
13302
|
+
},
|
|
13303
|
+
{
|
|
13304
|
+
name: "orderings30",
|
|
13305
|
+
possibleValues: range(30).map((i) => ({
|
|
13306
|
+
SHUFFLE_SEED: i
|
|
13307
|
+
}))
|
|
13121
13308
|
}
|
|
13122
13309
|
];
|
|
13123
13310
|
}
|
|
@@ -13146,70 +13333,320 @@ var HyperCapacityPathingSingleSectionSolver = class extends HyperParameterSuperv
|
|
|
13146
13333
|
}
|
|
13147
13334
|
};
|
|
13148
13335
|
|
|
13149
|
-
// lib/solvers/CapacityPathingSectionSolver/
|
|
13150
|
-
|
|
13151
|
-
|
|
13152
|
-
|
|
13153
|
-
|
|
13154
|
-
|
|
13155
|
-
|
|
13156
|
-
|
|
13157
|
-
|
|
13158
|
-
|
|
13159
|
-
|
|
13160
|
-
|
|
13161
|
-
|
|
13162
|
-
|
|
13163
|
-
|
|
13164
|
-
|
|
13165
|
-
|
|
13166
|
-
|
|
13167
|
-
|
|
13168
|
-
|
|
13169
|
-
|
|
13170
|
-
|
|
13171
|
-
|
|
13172
|
-
|
|
13173
|
-
|
|
13336
|
+
// lib/solvers/CapacityPathingSectionSolver/CachedHyperCapacityPathingSingleSectionSolver.ts
|
|
13337
|
+
import objectHash2 from "object-hash";
|
|
13338
|
+
var roundCapacity = (capacity) => Math.floor(capacity * 10) / 10;
|
|
13339
|
+
var CachedHyperCapacityPathingSingleSectionSolver = class extends HyperCapacityPathingSingleSectionSolver {
|
|
13340
|
+
cacheHit = false;
|
|
13341
|
+
cacheProvider;
|
|
13342
|
+
hasAttemptedToUseCache = false;
|
|
13343
|
+
sectionNodeIdSet;
|
|
13344
|
+
cachedSectionConnectionTerminals = null;
|
|
13345
|
+
sectionScore = 0;
|
|
13346
|
+
constructor(params) {
|
|
13347
|
+
params.nodeMap = params.nodeMap ?? new Map(params.sectionNodes.map((n) => [n.capacityMeshNodeId, n]));
|
|
13348
|
+
super(params);
|
|
13349
|
+
this.sectionNodeIdSet = new Set(
|
|
13350
|
+
params.sectionNodes.map((sn) => sn.capacityMeshNodeId)
|
|
13351
|
+
);
|
|
13352
|
+
this.cacheProvider = params.cacheProvider === void 0 ? getGlobalInMemoryCache() : params.cacheProvider;
|
|
13353
|
+
}
|
|
13354
|
+
_step() {
|
|
13355
|
+
if (!this.hasAttemptedToUseCache && this.cacheProvider) {
|
|
13356
|
+
if (this.attemptToUseCacheSync()) return;
|
|
13357
|
+
}
|
|
13358
|
+
super._step();
|
|
13359
|
+
if ((this.solved || this.failed) && this.cacheProvider) {
|
|
13360
|
+
this.saveToCacheSync();
|
|
13174
13361
|
}
|
|
13175
13362
|
}
|
|
13176
|
-
|
|
13177
|
-
|
|
13178
|
-
const
|
|
13179
|
-
|
|
13180
|
-
|
|
13181
|
-
|
|
13182
|
-
|
|
13183
|
-
|
|
13184
|
-
|
|
13185
|
-
|
|
13186
|
-
|
|
13187
|
-
|
|
13188
|
-
|
|
13189
|
-
|
|
13363
|
+
_computeBfsOrderingOfNodesInSection() {
|
|
13364
|
+
const seenNodeIds = new Set(this.constructorParams.centerNodeId);
|
|
13365
|
+
const ordering = [];
|
|
13366
|
+
const candidates = [
|
|
13367
|
+
{
|
|
13368
|
+
ancestorCapacitySum: 0,
|
|
13369
|
+
capacity: 0,
|
|
13370
|
+
g: 0,
|
|
13371
|
+
capacityMeshNodeId: this.constructorParams.centerNodeId
|
|
13372
|
+
}
|
|
13373
|
+
];
|
|
13374
|
+
while (candidates.length > 0) {
|
|
13375
|
+
candidates.sort((a, b) => b.g - a.g);
|
|
13376
|
+
const candidate = candidates.pop();
|
|
13377
|
+
if (!candidate) break;
|
|
13378
|
+
ordering.push(candidate.capacityMeshNodeId);
|
|
13379
|
+
const neighborNodeIds = this.constructorParams.nodeEdgeMap.get(candidate.capacityMeshNodeId).flatMap((edge) => edge.nodeIds).filter((nodeId) => !seenNodeIds.has(nodeId)).filter((nodeId) => this.sectionNodeIdSet.has(nodeId));
|
|
13380
|
+
for (const neighborNodeId of neighborNodeIds) {
|
|
13381
|
+
seenNodeIds.add(neighborNodeId);
|
|
13382
|
+
const neighbor = this.constructorParams.nodeMap.get(neighborNodeId);
|
|
13383
|
+
const capacity = getTunedTotalCapacity1(neighbor);
|
|
13384
|
+
candidates.push({
|
|
13385
|
+
ancestorCapacitySum: candidate.g,
|
|
13386
|
+
capacity,
|
|
13387
|
+
g: candidate.g + capacity,
|
|
13388
|
+
capacityMeshNodeId: neighborNodeId
|
|
13389
|
+
});
|
|
13190
13390
|
}
|
|
13191
13391
|
}
|
|
13192
|
-
|
|
13193
|
-
|
|
13194
|
-
|
|
13195
|
-
|
|
13196
|
-
|
|
13392
|
+
return ordering;
|
|
13393
|
+
}
|
|
13394
|
+
computeCacheKeyAndTransform() {
|
|
13395
|
+
const nodeOrdering = this._computeBfsOrderingOfNodesInSection();
|
|
13396
|
+
const realToCacheSpaceNodeIdMap = /* @__PURE__ */ new Map();
|
|
13397
|
+
const cacheSpaceToRealNodeIdMap = /* @__PURE__ */ new Map();
|
|
13398
|
+
nodeOrdering.forEach((realNodeId, i) => {
|
|
13399
|
+
const cacheNodeId = `node${i}`;
|
|
13400
|
+
realToCacheSpaceNodeIdMap.set(realNodeId, cacheNodeId);
|
|
13401
|
+
cacheSpaceToRealNodeIdMap.set(cacheNodeId, realNodeId);
|
|
13402
|
+
});
|
|
13403
|
+
const node_capacity_map = {};
|
|
13404
|
+
for (const realNodeId of nodeOrdering) {
|
|
13405
|
+
const cacheNodeId = realToCacheSpaceNodeIdMap.get(realNodeId);
|
|
13406
|
+
const node = this.constructorParams.nodeMap.get(realNodeId);
|
|
13407
|
+
const capacity = getTunedTotalCapacity1(node);
|
|
13408
|
+
node_capacity_map[cacheNodeId] = roundCapacity(capacity).toFixed(
|
|
13409
|
+
1
|
|
13410
|
+
);
|
|
13411
|
+
}
|
|
13412
|
+
const node_edge_map_set = /* @__PURE__ */ new Set();
|
|
13413
|
+
const node_edge_map = [];
|
|
13414
|
+
for (const realNodeId1 of nodeOrdering) {
|
|
13415
|
+
const cacheNodeId1 = realToCacheSpaceNodeIdMap.get(realNodeId1);
|
|
13416
|
+
const neighbors = this.constructorParams.nodeEdgeMap.get(realNodeId1) ?? [];
|
|
13417
|
+
for (const edge of neighbors) {
|
|
13418
|
+
const realNodeId2 = edge.nodeIds.find((id) => id !== realNodeId1);
|
|
13419
|
+
if (this.sectionNodeIdSet.has(realNodeId2)) {
|
|
13420
|
+
const cacheNodeId2 = realToCacheSpaceNodeIdMap.get(realNodeId2);
|
|
13421
|
+
const pair = [cacheNodeId1, cacheNodeId2].sort();
|
|
13422
|
+
const pairKey = `${pair[0]}-${pair[1]}`;
|
|
13423
|
+
if (!node_edge_map_set.has(pairKey)) {
|
|
13424
|
+
node_edge_map.push(pair);
|
|
13425
|
+
node_edge_map_set.add(pairKey);
|
|
13426
|
+
}
|
|
13427
|
+
}
|
|
13197
13428
|
}
|
|
13198
13429
|
}
|
|
13199
|
-
|
|
13200
|
-
|
|
13201
|
-
|
|
13202
|
-
|
|
13203
|
-
|
|
13430
|
+
node_edge_map.sort((a, b) => {
|
|
13431
|
+
if (a[0] !== b[0]) return a[0].localeCompare(b[0]);
|
|
13432
|
+
return a[1].localeCompare(b[1]);
|
|
13433
|
+
});
|
|
13434
|
+
const terminals = {};
|
|
13435
|
+
const cacheSpaceToRealConnectionId = /* @__PURE__ */ new Map();
|
|
13436
|
+
for (const conn of this.constructorParams.sectionConnectionTerminals) {
|
|
13437
|
+
const cacheStartNodeId = realToCacheSpaceNodeIdMap.get(conn.startNodeId);
|
|
13438
|
+
const cacheEndNodeId = realToCacheSpaceNodeIdMap.get(conn.endNodeId);
|
|
13439
|
+
const [sortedStartId, sortedEndId] = [
|
|
13440
|
+
cacheStartNodeId,
|
|
13441
|
+
cacheEndNodeId
|
|
13442
|
+
].sort();
|
|
13443
|
+
const cacheSpaceConnectionId = `${sortedStartId}->${sortedEndId}`;
|
|
13444
|
+
terminals[cacheSpaceConnectionId] = {
|
|
13445
|
+
start: sortedStartId,
|
|
13446
|
+
end: sortedEndId
|
|
13447
|
+
};
|
|
13448
|
+
cacheSpaceToRealConnectionId.set(
|
|
13449
|
+
cacheSpaceConnectionId,
|
|
13450
|
+
// Use the canonically sorted key
|
|
13451
|
+
conn.connectionName
|
|
13452
|
+
);
|
|
13453
|
+
}
|
|
13454
|
+
const cacheKeyContent = {
|
|
13455
|
+
node_capacity_map,
|
|
13456
|
+
node_edge_map,
|
|
13457
|
+
terminals
|
|
13458
|
+
};
|
|
13459
|
+
const cacheKey = `capacitypathing:${objectHash2(cacheKeyContent)}`;
|
|
13460
|
+
const cacheToSolveSpaceTransform = {
|
|
13461
|
+
cacheSpaceToRealConnectionId,
|
|
13462
|
+
cacheSpaceToRealNodeId: cacheSpaceToRealNodeIdMap
|
|
13463
|
+
};
|
|
13464
|
+
this.cacheKey = cacheKey;
|
|
13465
|
+
this.cacheToSolveSpaceTransform = cacheToSolveSpaceTransform;
|
|
13466
|
+
return { cacheKey, cacheToSolveSpaceTransform };
|
|
13467
|
+
}
|
|
13468
|
+
applyCachedSolution(cachedSolution) {
|
|
13469
|
+
if (!this.cacheToSolveSpaceTransform) {
|
|
13470
|
+
console.error(
|
|
13471
|
+
"Cache transform not available, cannot apply cached solution."
|
|
13472
|
+
);
|
|
13473
|
+
this.failed = true;
|
|
13474
|
+
return;
|
|
13475
|
+
}
|
|
13476
|
+
if (!cachedSolution.success) {
|
|
13477
|
+
this.failed = true;
|
|
13478
|
+
this.cacheHit = true;
|
|
13479
|
+
return;
|
|
13480
|
+
}
|
|
13481
|
+
this.cachedSectionConnectionTerminals = [];
|
|
13482
|
+
const { cacheSpaceToRealNodeId, cacheSpaceToRealConnectionId } = this.cacheToSolveSpaceTransform;
|
|
13483
|
+
for (const [cacheConnId, cachePathNodeIds] of Object.entries(
|
|
13484
|
+
cachedSolution.solutionPaths
|
|
13485
|
+
)) {
|
|
13486
|
+
const realConnectionName = cacheSpaceToRealConnectionId.get(
|
|
13487
|
+
cacheConnId
|
|
13488
|
+
);
|
|
13489
|
+
if (!realConnectionName) {
|
|
13490
|
+
console.warn(`Could not find real connection name for ${cacheConnId}`);
|
|
13491
|
+
continue;
|
|
13492
|
+
}
|
|
13493
|
+
const originalTerminal = this.constructorParams.sectionConnectionTerminals.find(
|
|
13494
|
+
(t) => t.connectionName === realConnectionName
|
|
13495
|
+
);
|
|
13496
|
+
if (!originalTerminal) {
|
|
13497
|
+
console.warn(
|
|
13498
|
+
`Could not find original terminal for connection name ${realConnectionName}`
|
|
13499
|
+
);
|
|
13500
|
+
continue;
|
|
13501
|
+
}
|
|
13502
|
+
const realPathNodes = cachePathNodeIds.map(
|
|
13503
|
+
(cacheNodeId) => {
|
|
13504
|
+
const realNodeId = cacheSpaceToRealNodeId.get(cacheNodeId);
|
|
13505
|
+
if (!realNodeId) {
|
|
13506
|
+
throw new Error(
|
|
13507
|
+
`Could not map cache node ID ${cacheNodeId} to real node ID for connection ${realConnectionName}`
|
|
13508
|
+
);
|
|
13509
|
+
}
|
|
13510
|
+
const node = this.constructorParams.nodeMap.get(realNodeId);
|
|
13511
|
+
if (!node) {
|
|
13512
|
+
throw new Error(
|
|
13513
|
+
`Could not find node with ID ${realNodeId} in nodeMap for connection ${realConnectionName}`
|
|
13514
|
+
);
|
|
13515
|
+
}
|
|
13516
|
+
return node;
|
|
13517
|
+
}
|
|
13518
|
+
);
|
|
13519
|
+
this.cachedSectionConnectionTerminals.push({
|
|
13520
|
+
...originalTerminal,
|
|
13521
|
+
path: realPathNodes
|
|
13204
13522
|
});
|
|
13205
13523
|
}
|
|
13524
|
+
this.sectionScore = cachedSolution.sectionScore;
|
|
13525
|
+
this.solved = true;
|
|
13526
|
+
this.cacheHit = true;
|
|
13527
|
+
}
|
|
13528
|
+
attemptToUseCacheSync() {
|
|
13529
|
+
this.hasAttemptedToUseCache = true;
|
|
13530
|
+
if (!this.cacheProvider?.isSyncCache) {
|
|
13531
|
+
console.log(
|
|
13532
|
+
"Cache provider is not synchronous, skipping sync cache check."
|
|
13533
|
+
);
|
|
13534
|
+
return false;
|
|
13535
|
+
}
|
|
13536
|
+
if (!this.cacheKey) {
|
|
13537
|
+
this.computeCacheKeyAndTransform();
|
|
13538
|
+
}
|
|
13539
|
+
if (!this.cacheKey) {
|
|
13540
|
+
console.error("Failed to compute cache key.");
|
|
13541
|
+
return false;
|
|
13542
|
+
}
|
|
13543
|
+
try {
|
|
13544
|
+
const cachedSolution = this.cacheProvider.getCachedSolutionSync(
|
|
13545
|
+
this.cacheKey
|
|
13546
|
+
);
|
|
13547
|
+
if (cachedSolution) {
|
|
13548
|
+
this.applyCachedSolution(
|
|
13549
|
+
cachedSolution
|
|
13550
|
+
);
|
|
13551
|
+
return true;
|
|
13552
|
+
}
|
|
13553
|
+
} catch (error) {
|
|
13554
|
+
console.error("Error attempting to use cache:", error);
|
|
13555
|
+
}
|
|
13556
|
+
return false;
|
|
13557
|
+
}
|
|
13558
|
+
saveToCacheSync() {
|
|
13559
|
+
if (!this.cacheKey) {
|
|
13560
|
+
console.error("Cannot save to cache without cache key.");
|
|
13561
|
+
return;
|
|
13562
|
+
}
|
|
13563
|
+
if (!this.cacheToSolveSpaceTransform) {
|
|
13564
|
+
console.error(
|
|
13565
|
+
"Cache transform not available, cannot save solution to cache."
|
|
13566
|
+
);
|
|
13567
|
+
return;
|
|
13568
|
+
}
|
|
13569
|
+
let cachedSolution;
|
|
13570
|
+
if (this.failed) {
|
|
13571
|
+
cachedSolution = { success: false };
|
|
13572
|
+
} else if (this.solved) {
|
|
13573
|
+
const solutionPathsInCacheSpace = {};
|
|
13574
|
+
const { cacheSpaceToRealNodeId, cacheSpaceToRealConnectionId } = this.cacheToSolveSpaceTransform;
|
|
13575
|
+
const realToCacheSpaceNodeId = /* @__PURE__ */ new Map();
|
|
13576
|
+
for (const [cacheId, realId] of cacheSpaceToRealNodeId) {
|
|
13577
|
+
realToCacheSpaceNodeId.set(realId, cacheId);
|
|
13578
|
+
}
|
|
13579
|
+
const realToCacheSpaceConnectionId = /* @__PURE__ */ new Map();
|
|
13580
|
+
for (const [cacheConnId, realConnName] of cacheSpaceToRealConnectionId) {
|
|
13581
|
+
realToCacheSpaceConnectionId.set(realConnName, cacheConnId);
|
|
13582
|
+
}
|
|
13583
|
+
const realSolutionPaths = [];
|
|
13584
|
+
if (super.sectionConnectionTerminals) {
|
|
13585
|
+
for (const terminal of super.sectionConnectionTerminals) {
|
|
13586
|
+
if (terminal.path && terminal.path.length > 0) {
|
|
13587
|
+
const realPathNodeIds = terminal.path.map(
|
|
13588
|
+
(node) => node.capacityMeshNodeId
|
|
13589
|
+
);
|
|
13590
|
+
realSolutionPaths.push([terminal.connectionName, realPathNodeIds]);
|
|
13591
|
+
}
|
|
13592
|
+
}
|
|
13593
|
+
}
|
|
13594
|
+
for (const [realConnectionName, realPathNodeIds] of realSolutionPaths) {
|
|
13595
|
+
const cacheConnectionId = realToCacheSpaceConnectionId.get(realConnectionName);
|
|
13596
|
+
if (!cacheConnectionId) {
|
|
13597
|
+
console.warn(
|
|
13598
|
+
`Could not find cache space connection ID for ${realConnectionName} when saving to cache.`
|
|
13599
|
+
);
|
|
13600
|
+
continue;
|
|
13601
|
+
}
|
|
13602
|
+
const cachePathNodeIds = realPathNodeIds.map((realNodeId) => {
|
|
13603
|
+
const cacheNodeId = realToCacheSpaceNodeId.get(realNodeId);
|
|
13604
|
+
if (!cacheNodeId) {
|
|
13605
|
+
throw new Error(
|
|
13606
|
+
`Could not map real node ID ${realNodeId} to cache node ID for connection ${realConnectionName} when saving to cache.`
|
|
13607
|
+
);
|
|
13608
|
+
}
|
|
13609
|
+
return cacheNodeId;
|
|
13610
|
+
});
|
|
13611
|
+
solutionPathsInCacheSpace[cacheConnectionId] = cachePathNodeIds;
|
|
13612
|
+
}
|
|
13613
|
+
cachedSolution = {
|
|
13614
|
+
success: true,
|
|
13615
|
+
sectionScore: this.sectionScore,
|
|
13616
|
+
solutionPaths: solutionPathsInCacheSpace
|
|
13617
|
+
};
|
|
13618
|
+
} else {
|
|
13619
|
+
return;
|
|
13620
|
+
}
|
|
13621
|
+
try {
|
|
13622
|
+
this.cacheProvider?.setCachedSolutionSync(this.cacheKey, cachedSolution);
|
|
13623
|
+
} catch (error) {
|
|
13624
|
+
console.error("Error saving solution to cache:", error);
|
|
13625
|
+
}
|
|
13626
|
+
}
|
|
13627
|
+
get sectionConnectionTerminals() {
|
|
13628
|
+
if (this.cacheHit && this.solved && this.cachedSectionConnectionTerminals) {
|
|
13629
|
+
console.log("returning the cached section connection terminals");
|
|
13630
|
+
return this.cachedSectionConnectionTerminals;
|
|
13631
|
+
}
|
|
13632
|
+
return super.sectionConnectionTerminals;
|
|
13633
|
+
}
|
|
13634
|
+
visualize() {
|
|
13635
|
+
if (!this.cacheHit) return super.visualize();
|
|
13636
|
+
const graphics = visualizeSection({
|
|
13637
|
+
sectionNodes: this.constructorParams.sectionNodes,
|
|
13638
|
+
sectionEdges: this.constructorParams.sectionEdges,
|
|
13639
|
+
sectionConnectionTerminals: this.cachedSectionConnectionTerminals,
|
|
13640
|
+
completedPaths: this.cachedSectionConnectionTerminals.map((t) => ({
|
|
13641
|
+
connectionName: t.connectionName,
|
|
13642
|
+
path: t.path
|
|
13643
|
+
})),
|
|
13644
|
+
nodeMap: this.constructorParams.nodeMap,
|
|
13645
|
+
colorMap: this.constructorParams.colorMap,
|
|
13646
|
+
title: "CachedHyperCapacityPathingSingleSectionSolver"
|
|
13647
|
+
});
|
|
13648
|
+
return graphics;
|
|
13206
13649
|
}
|
|
13207
|
-
return {
|
|
13208
|
-
sectionConnectionTerminals,
|
|
13209
|
-
sectionNodes,
|
|
13210
|
-
sectionEdges,
|
|
13211
|
-
centerNodeId
|
|
13212
|
-
};
|
|
13213
13650
|
};
|
|
13214
13651
|
|
|
13215
13652
|
// lib/solvers/CapacityPathingSectionSolver/CapacityPathingMultiSectionSolver.ts
|
|
@@ -13222,8 +13659,10 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13222
13659
|
// Initialize here
|
|
13223
13660
|
colorMap;
|
|
13224
13661
|
initialSolver;
|
|
13662
|
+
cacheProvider;
|
|
13225
13663
|
stage = "initialization";
|
|
13226
13664
|
nodeMap = /* @__PURE__ */ new Map();
|
|
13665
|
+
allNodeIdsSet;
|
|
13227
13666
|
usedNodeCapacityMap = /* @__PURE__ */ new Map();
|
|
13228
13667
|
totalNodeCapacityMap = /* @__PURE__ */ new Map();
|
|
13229
13668
|
// Added
|
|
@@ -13233,16 +13672,22 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13233
13672
|
sectionSolver = null;
|
|
13234
13673
|
currentScheduleIndex = 0;
|
|
13235
13674
|
stats;
|
|
13675
|
+
// Adjusting this schedule is a trade-off between optimization speed and quality.
|
|
13236
13676
|
OPTIMIZATION_SCHEDULE = [
|
|
13237
13677
|
{
|
|
13238
13678
|
MAX_ATTEMPTS_PER_NODE: 1,
|
|
13239
|
-
MAX_EXPANSION_DEGREES:
|
|
13240
|
-
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: 0.
|
|
13679
|
+
MAX_EXPANSION_DEGREES: 3,
|
|
13680
|
+
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: 0.05
|
|
13241
13681
|
},
|
|
13242
13682
|
{
|
|
13243
13683
|
MAX_ATTEMPTS_PER_NODE: 2,
|
|
13244
|
-
MAX_EXPANSION_DEGREES:
|
|
13245
|
-
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: 0.
|
|
13684
|
+
MAX_EXPANSION_DEGREES: 5,
|
|
13685
|
+
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: 0.2
|
|
13686
|
+
},
|
|
13687
|
+
{
|
|
13688
|
+
MAX_ATTEMPTS_PER_NODE: 3,
|
|
13689
|
+
MAX_EXPANSION_DEGREES: 7,
|
|
13690
|
+
MINIMUM_PROBABILITY_OF_FAILURE_TO_OPTIMIZE: 0.9
|
|
13246
13691
|
}
|
|
13247
13692
|
];
|
|
13248
13693
|
get currentSchedule() {
|
|
@@ -13254,6 +13699,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13254
13699
|
successfulOptimizations: 0,
|
|
13255
13700
|
failedOptimizations: 0,
|
|
13256
13701
|
failedSectionSolvers: 0,
|
|
13702
|
+
startingScore: 0,
|
|
13257
13703
|
scheduleScores: this.OPTIMIZATION_SCHEDULE.map(
|
|
13258
13704
|
({ MAX_EXPANSION_DEGREES }) => ({
|
|
13259
13705
|
maxExpansionDegrees: MAX_EXPANSION_DEGREES,
|
|
@@ -13264,6 +13710,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13264
13710
|
)
|
|
13265
13711
|
};
|
|
13266
13712
|
this.MAX_ITERATIONS = 1e7;
|
|
13713
|
+
this.cacheProvider = params.cacheProvider;
|
|
13267
13714
|
this.simpleRouteJson = params.simpleRouteJson;
|
|
13268
13715
|
this.nodes = params.nodes;
|
|
13269
13716
|
this.edges = params.edges;
|
|
@@ -13284,6 +13731,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13284
13731
|
const totalCapacity = this.initialSolver.getTotalCapacity(node);
|
|
13285
13732
|
this.totalNodeCapacityMap.set(node.capacityMeshNodeId, totalCapacity);
|
|
13286
13733
|
}
|
|
13734
|
+
this.allNodeIdsSet = new Set(this.nodes.map((n) => n.capacityMeshNodeId));
|
|
13287
13735
|
}
|
|
13288
13736
|
_stepInitialization() {
|
|
13289
13737
|
this.initialSolver?.step();
|
|
@@ -13302,6 +13750,12 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13302
13750
|
this.nodeOptimizationAttemptCountMap.set(node.capacityMeshNodeId, 0);
|
|
13303
13751
|
}
|
|
13304
13752
|
this.connectionsWithNodes = this.initialSolver.connectionsWithNodes;
|
|
13753
|
+
this.stats.startingScore = computeSectionScore({
|
|
13754
|
+
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
13755
|
+
usedNodeCapacityMap: this.usedNodeCapacityMap,
|
|
13756
|
+
nodeMap: this.nodeMap,
|
|
13757
|
+
sectionNodeIds: this.allNodeIdsSet
|
|
13758
|
+
});
|
|
13305
13759
|
this.stage = "section-optimization";
|
|
13306
13760
|
}
|
|
13307
13761
|
}
|
|
@@ -13353,9 +13807,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13353
13807
|
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
13354
13808
|
usedNodeCapacityMap: this.usedNodeCapacityMap,
|
|
13355
13809
|
nodeMap: this.nodeMap,
|
|
13356
|
-
sectionNodeIds:
|
|
13357
|
-
this.nodes.map((node) => node.capacityMeshNodeId)
|
|
13358
|
-
)
|
|
13810
|
+
sectionNodeIds: this.allNodeIdsSet
|
|
13359
13811
|
})
|
|
13360
13812
|
};
|
|
13361
13813
|
}
|
|
@@ -13383,13 +13835,17 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13383
13835
|
});
|
|
13384
13836
|
this.stats.scheduleScores[this.currentScheduleIndex].sectionAttempts++;
|
|
13385
13837
|
this.currentSection = section;
|
|
13386
|
-
this.sectionSolver = new
|
|
13838
|
+
this.sectionSolver = new CachedHyperCapacityPathingSingleSectionSolver({
|
|
13387
13839
|
sectionNodes: this.currentSection.sectionNodes,
|
|
13388
13840
|
sectionEdges: this.currentSection.sectionEdges,
|
|
13389
13841
|
sectionConnectionTerminals: this.currentSection.sectionConnectionTerminals,
|
|
13390
13842
|
colorMap: this.colorMap,
|
|
13391
13843
|
centerNodeId: this.currentSection.centerNodeId,
|
|
13392
|
-
nodeEdgeMap: this.nodeEdgeMap
|
|
13844
|
+
nodeEdgeMap: this.nodeEdgeMap,
|
|
13845
|
+
hyperParameters: {
|
|
13846
|
+
EXPANSION_DEGREES: this.currentSchedule.MAX_EXPANSION_DEGREES
|
|
13847
|
+
},
|
|
13848
|
+
cacheProvider: this.cacheProvider
|
|
13393
13849
|
});
|
|
13394
13850
|
this.activeSubSolver = this.sectionSolver;
|
|
13395
13851
|
this.nodeOptimizationAttemptCountMap.set(
|
|
@@ -13409,18 +13865,19 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13409
13865
|
return;
|
|
13410
13866
|
}
|
|
13411
13867
|
if (this.sectionSolver.solved) {
|
|
13412
|
-
const
|
|
13413
|
-
const
|
|
13868
|
+
const sectionConnectionTerminals = this.sectionSolver.sectionConnectionTerminals;
|
|
13869
|
+
const sectionNodes = this.sectionSolver.sectionNodes;
|
|
13870
|
+
const centerNodeId = this.sectionSolver.centerNodeId;
|
|
13414
13871
|
this.sectionSolver = null;
|
|
13415
13872
|
this.activeSubSolver = null;
|
|
13416
|
-
if (!
|
|
13873
|
+
if (!sectionConnectionTerminals) {
|
|
13417
13874
|
console.warn(
|
|
13418
13875
|
`Pathing sub-solver for section ${this.currentSection.centerNodeId} did not complete successfully. Discarding results.`
|
|
13419
13876
|
);
|
|
13420
13877
|
return;
|
|
13421
13878
|
}
|
|
13422
13879
|
const sectionNodeIds = new Set(
|
|
13423
|
-
|
|
13880
|
+
sectionNodes.map((n) => n.capacityMeshNodeId)
|
|
13424
13881
|
);
|
|
13425
13882
|
const beforeScore = computeSectionScore({
|
|
13426
13883
|
totalNodeCapacityMap: this.totalNodeCapacityMap,
|
|
@@ -13429,7 +13886,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13429
13886
|
sectionNodeIds
|
|
13430
13887
|
});
|
|
13431
13888
|
const afterUsedCapacityMap = new Map(this.usedNodeCapacityMap);
|
|
13432
|
-
const newSectionPaths =
|
|
13889
|
+
const newSectionPaths = sectionConnectionTerminals;
|
|
13433
13890
|
for (const terminal of newSectionPaths) {
|
|
13434
13891
|
const originalConnection = this.connectionsWithNodes.find(
|
|
13435
13892
|
(conn) => conn.connection.name === terminal.connectionName
|
|
@@ -13466,7 +13923,10 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13466
13923
|
});
|
|
13467
13924
|
if (afterScore > beforeScore) {
|
|
13468
13925
|
this.stats.successfulOptimizations++;
|
|
13469
|
-
this._mergeSolvedSectionPaths(
|
|
13926
|
+
this._mergeSolvedSectionPaths({
|
|
13927
|
+
centerNodeId,
|
|
13928
|
+
sectionConnectionTerminals
|
|
13929
|
+
});
|
|
13470
13930
|
this._recalculateNodeCapacityUsage();
|
|
13471
13931
|
} else {
|
|
13472
13932
|
this.stats.failedOptimizations++;
|
|
@@ -13477,16 +13937,11 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13477
13937
|
* Merges the paths found by a successful section solver back into the main
|
|
13478
13938
|
* connectionsWithNodes list.
|
|
13479
13939
|
*/
|
|
13480
|
-
_mergeSolvedSectionPaths(
|
|
13481
|
-
|
|
13482
|
-
|
|
13483
|
-
|
|
13484
|
-
|
|
13485
|
-
);
|
|
13486
|
-
return;
|
|
13487
|
-
}
|
|
13488
|
-
const solvedTerminals = solvedSectionSolver.sectionConnectionTerminals;
|
|
13489
|
-
for (const solvedTerminal of solvedTerminals) {
|
|
13940
|
+
_mergeSolvedSectionPaths({
|
|
13941
|
+
centerNodeId,
|
|
13942
|
+
sectionConnectionTerminals
|
|
13943
|
+
}) {
|
|
13944
|
+
for (const solvedTerminal of sectionConnectionTerminals) {
|
|
13490
13945
|
if (!solvedTerminal.path) {
|
|
13491
13946
|
console.warn(
|
|
13492
13947
|
`No path found for connection ${solvedTerminal.connectionName} in section ${centerNodeId}`
|
|
@@ -13498,7 +13953,7 @@ var CapacityPathingMultiSectionSolver = class extends BaseSolver {
|
|
|
13498
13953
|
);
|
|
13499
13954
|
if (!originalConnection || !originalConnection.path) {
|
|
13500
13955
|
console.warn(
|
|
13501
|
-
`Original connection or path not found for ${solvedTerminal.connectionName} while merging section ${
|
|
13956
|
+
`Original connection or path not found for ${solvedTerminal.connectionName} while merging section ${centerNodeId}`
|
|
13502
13957
|
);
|
|
13503
13958
|
continue;
|
|
13504
13959
|
}
|
|
@@ -15845,7 +16300,7 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
15845
16300
|
}
|
|
15846
16301
|
this.connMap = getConnectivityMapFromSimpleRouteJson(srj);
|
|
15847
16302
|
this.colorMap = getColorMap(srj, this.connMap);
|
|
15848
|
-
this.cacheProvider = opts.cacheProvider
|
|
16303
|
+
this.cacheProvider = opts.cacheProvider === void 0 ? getGlobalInMemoryCache() : opts.cacheProvider === null ? null : opts.cacheProvider;
|
|
15849
16304
|
this.startTimeOfPhase = {};
|
|
15850
16305
|
this.endTimeOfPhase = {};
|
|
15851
16306
|
this.timeSpentOnPhase = {};
|
|
@@ -15969,6 +16424,7 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
15969
16424
|
nodes: cms.capacityNodes,
|
|
15970
16425
|
edges: cms.edgeSolver?.edges || [],
|
|
15971
16426
|
colorMap: cms.colorMap,
|
|
16427
|
+
cacheProvider: cms.cacheProvider,
|
|
15972
16428
|
hyperParameters: {
|
|
15973
16429
|
MAX_CAPACITY_FACTOR: 1
|
|
15974
16430
|
}
|
|
@@ -16311,7 +16767,12 @@ var AutoroutingPipelineSolver = class extends BaseSolver {
|
|
|
16311
16767
|
var CapacityMeshSolver = AutoroutingPipelineSolver;
|
|
16312
16768
|
export {
|
|
16313
16769
|
CapacityMeshSolver,
|
|
16770
|
+
InMemoryCache,
|
|
16771
|
+
LocalStorageCache,
|
|
16314
16772
|
calculateOptimalCapacityDepth,
|
|
16315
|
-
|
|
16773
|
+
getGlobalInMemoryCache,
|
|
16774
|
+
getGlobalLocalStorageCache,
|
|
16775
|
+
getTunedTotalCapacity1,
|
|
16776
|
+
setupGlobalCaches
|
|
16316
16777
|
};
|
|
16317
16778
|
//# sourceMappingURL=index.js.map
|