@tscircuit/hypergraph 0.0.68 → 0.0.70
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 +102 -5
- package/dist/index.js +841 -213
- package/package.json +1 -1
package/dist/index.d.ts
CHANGED
|
@@ -83,6 +83,10 @@ type SerializedRegionPortAssignment = {
|
|
|
83
83
|
type SerializedHyperGraph = {
|
|
84
84
|
ports: SerializedGraphPort[];
|
|
85
85
|
regions: SerializedGraphRegion[];
|
|
86
|
+
solvedRoutes?: SerializedSolvedRoute[];
|
|
87
|
+
connections?: SerializedConnection[];
|
|
88
|
+
_sectionRouteBindings?: SerializedSectionRouteBinding[];
|
|
89
|
+
_sectionCentralRegionId?: RegionId;
|
|
86
90
|
};
|
|
87
91
|
type SerializedCandidate = {
|
|
88
92
|
portId: PortId;
|
|
@@ -100,8 +104,10 @@ type SerializedSolvedRoute = {
|
|
|
100
104
|
connection: SerializedConnection;
|
|
101
105
|
requiredRip: boolean;
|
|
102
106
|
};
|
|
103
|
-
type
|
|
104
|
-
|
|
107
|
+
type SerializedSectionRouteBinding = {
|
|
108
|
+
connectionId: ConnectionId;
|
|
109
|
+
solvedPathStartIndex: number;
|
|
110
|
+
solvedPathEndIndex: number;
|
|
105
111
|
};
|
|
106
112
|
type Connection = {
|
|
107
113
|
connectionId: ConnectionId;
|
|
@@ -120,11 +126,13 @@ declare const convertConnectionsToSerializedConnections: (connections: Connectio
|
|
|
120
126
|
|
|
121
127
|
declare const convertHyperGraphToSerializedHyperGraph: (graph: HyperGraph) => SerializedHyperGraph;
|
|
122
128
|
|
|
129
|
+
declare const createBlankHyperGraph: (inputGraph: SerializedHyperGraph) => SerializedHyperGraph;
|
|
130
|
+
|
|
123
131
|
declare const extractSectionOfHyperGraph: (input: {
|
|
124
|
-
graph:
|
|
132
|
+
graph: SerializedHyperGraph;
|
|
125
133
|
centralRegionId: RegionId;
|
|
126
134
|
expansionHopsFromCentralRegion: number;
|
|
127
|
-
}) =>
|
|
135
|
+
}) => SerializedHyperGraph;
|
|
128
136
|
|
|
129
137
|
type Node = {
|
|
130
138
|
f: number;
|
|
@@ -335,6 +343,13 @@ declare class HyperGraphSolver<RegionType extends Region = Region, RegionPortTyp
|
|
|
335
343
|
_step(): void;
|
|
336
344
|
}
|
|
337
345
|
|
|
346
|
+
declare const reattachSectionToGraph: (input: {
|
|
347
|
+
fullGraph: SerializedHyperGraph;
|
|
348
|
+
solvedSectionGraph: SerializedHyperGraph;
|
|
349
|
+
}) => SerializedHyperGraph;
|
|
350
|
+
|
|
351
|
+
declare const pruneDeadEndPorts: (graph: HyperGraph, retainedPortIds?: Iterable<PortId>) => HyperGraph;
|
|
352
|
+
|
|
338
353
|
type CreateHyperGraphSolverInput = {
|
|
339
354
|
inputGraph: HyperGraph | SerializedHyperGraph;
|
|
340
355
|
inputConnections: (Connection | SerializedConnection)[];
|
|
@@ -431,6 +446,88 @@ declare class HyperGraphSectionOptimizer extends BaseSolver {
|
|
|
431
446
|
_step(): void;
|
|
432
447
|
}
|
|
433
448
|
|
|
449
|
+
type CreateSectionSolverInput = {
|
|
450
|
+
inputGraph: SerializedHyperGraph;
|
|
451
|
+
inputConnections: SerializedConnection[];
|
|
452
|
+
inputSolvedRoutes: SerializedSolvedRoute[];
|
|
453
|
+
};
|
|
454
|
+
type HyperGraphSectionOptimizer2Input = {
|
|
455
|
+
inputGraph: SerializedHyperGraph;
|
|
456
|
+
inputConnections?: SerializedConnection[];
|
|
457
|
+
inputSolvedRoutes?: SerializedSolvedRoute[];
|
|
458
|
+
sectionExpansionHops?: number;
|
|
459
|
+
maxTargetRegionAttempts?: number;
|
|
460
|
+
maxSectionAttempts?: number;
|
|
461
|
+
minCentralRegionCost?: number;
|
|
462
|
+
effort?: number;
|
|
463
|
+
expansionHopsFromCentralRegion?: number;
|
|
464
|
+
MAX_ATTEMPTS_PER_REGION?: number;
|
|
465
|
+
MAX_ATTEMPTS_PER_SECTION?: number;
|
|
466
|
+
ACCEPTABLE_CENTRAL_REGION_COST?: number;
|
|
467
|
+
};
|
|
468
|
+
type NormalizedHyperGraphSectionOptimizer2Input = {
|
|
469
|
+
inputGraph: SerializedHyperGraph;
|
|
470
|
+
inputConnections: SerializedConnection[];
|
|
471
|
+
inputSolvedRoutes: SerializedSolvedRoute[];
|
|
472
|
+
sectionExpansionHops: number;
|
|
473
|
+
maxTargetRegionAttempts: number;
|
|
474
|
+
maxSectionAttempts: number;
|
|
475
|
+
minCentralRegionCost: number;
|
|
476
|
+
effort: number;
|
|
477
|
+
};
|
|
478
|
+
type SectionSolveAttempt = {
|
|
479
|
+
targetRegionId: RegionId;
|
|
480
|
+
sectionRegionIds: Set<RegionId>;
|
|
481
|
+
fullGraphSnapshot: SerializedHyperGraph;
|
|
482
|
+
blankSectionProblem: SerializedHyperGraph;
|
|
483
|
+
currentSectionCost: number;
|
|
484
|
+
};
|
|
485
|
+
declare class HyperGraphSectionOptimizer2 extends BaseSolver {
|
|
486
|
+
readonly config: NormalizedHyperGraphSectionOptimizer2Input;
|
|
487
|
+
readonly rootSolver: HyperGraphSolver<Region, RegionPort>;
|
|
488
|
+
graph: HyperGraph;
|
|
489
|
+
connections: Connection[];
|
|
490
|
+
solvedRoutes: SolvedRoute[];
|
|
491
|
+
activeAttempt: SectionSolveAttempt | null;
|
|
492
|
+
targetRegionAttemptCounts: Map<string, number>;
|
|
493
|
+
attemptedSectionCount: number;
|
|
494
|
+
activeSubSolver: HyperGraphSolver<Region, RegionPort> | null;
|
|
495
|
+
constructor(input: HyperGraphSectionOptimizer2Input);
|
|
496
|
+
getSolverName(): string;
|
|
497
|
+
getConstructorParams(): {
|
|
498
|
+
inputGraph: SerializedHyperGraph;
|
|
499
|
+
inputConnections: SerializedConnection[];
|
|
500
|
+
inputSolvedRoutes: SerializedSolvedRoute[];
|
|
501
|
+
sectionExpansionHops: number;
|
|
502
|
+
maxTargetRegionAttempts: number;
|
|
503
|
+
maxSectionAttempts: number;
|
|
504
|
+
minCentralRegionCost: number;
|
|
505
|
+
effort: number;
|
|
506
|
+
};
|
|
507
|
+
getOutput(): SolvedRoute[];
|
|
508
|
+
_setup(): void;
|
|
509
|
+
visualize(): GraphicsObject;
|
|
510
|
+
protected createHyperGraphSolver(input: CreateSectionSolverInput): HyperGraphSolver<Region, RegionPort>;
|
|
511
|
+
getCostOfCentralRegion(region: Region): number;
|
|
512
|
+
getSectionCost(input: {
|
|
513
|
+
solvedGraph: SerializedHyperGraph;
|
|
514
|
+
sectionRegionIds: Set<RegionId>;
|
|
515
|
+
}): number;
|
|
516
|
+
_step(): void;
|
|
517
|
+
private startNextSectionAttempt;
|
|
518
|
+
private selectTargetRegion;
|
|
519
|
+
private createSectionSolveAttempt;
|
|
520
|
+
private acceptMergedGraph;
|
|
521
|
+
private rejectActiveAttempt;
|
|
522
|
+
private clearActiveAttempt;
|
|
523
|
+
private bumpTargetRegionAttemptCount;
|
|
524
|
+
private serializeSolvedGraph;
|
|
525
|
+
private deserializeSolvedRoutes;
|
|
526
|
+
private getSectionRegionIds;
|
|
527
|
+
private pruneSectionForBlanking;
|
|
528
|
+
private getRegionSolutionCost;
|
|
529
|
+
}
|
|
530
|
+
|
|
434
531
|
type Bounds$1 = {
|
|
435
532
|
minX: number;
|
|
436
533
|
minY: number;
|
|
@@ -1312,4 +1409,4 @@ declare function generateConvexViaTopologyRegions(opts: {
|
|
|
1312
1409
|
};
|
|
1313
1410
|
};
|
|
1314
1411
|
|
|
1315
|
-
export { type Bounds$1 as Bounds, type BuildOpts, type Candidate, ConnectBuilder, type ConnectOpts, type Connection, type ConnectionId, type ConvexViaGraphFromXYConnectionsResult, type CreateHyperGraphSolver, type CreateHyperGraphSolverInput, type GScore, type GraphEdgeId, type HyperGraph, type HyperGraphSection, HyperGraphSectionOptimizer, HyperGraphSolver, type JPort, type JRegion, JUMPER_GRAPH_SOLVER_DEFAULTS, type JumperGraph, JumperGraphSolver, type JumperGraphWithConnections, type NetworkId, type PortAssignment, PortBuilder, type PortData, type PortId, type PortSpread, type Region, RegionBuilder, type RegionData, type RegionId, type RegionPort, type RegionPortAssignment, type RegionRef, type RouteSegment, type SectionRoute, type SerializedCandidate, type SerializedConnection, type SerializedGraphPort, type SerializedGraphRegion, type SerializedHyperGraph, type
|
|
1412
|
+
export { type Bounds$1 as Bounds, type BuildOpts, type Candidate, ConnectBuilder, type ConnectOpts, type Connection, type ConnectionId, type ConvexViaGraphFromXYConnectionsResult, type CreateHyperGraphSolver, type CreateHyperGraphSolverInput, type CreateSectionSolverInput, type GScore, type GraphEdgeId, type HyperGraph, type HyperGraphSection, HyperGraphSectionOptimizer, HyperGraphSectionOptimizer2, type HyperGraphSectionOptimizer2Input, HyperGraphSolver, type JPort, type JRegion, JUMPER_GRAPH_SOLVER_DEFAULTS, type JumperGraph, JumperGraphSolver, type JumperGraphWithConnections, type NetworkId, type PortAssignment, PortBuilder, type PortData, type PortId, type PortSpread, type Region, RegionBuilder, type RegionData, type RegionId, type RegionPort, type RegionPortAssignment, type RegionRef, type RouteSegment, type SectionRoute, type SerializedCandidate, type SerializedConnection, type SerializedGraphPort, type SerializedGraphRegion, type SerializedHyperGraph, type SerializedRegionPortAssignment, type SerializedSectionRouteBinding, type SerializedSolvedRoute, type SharedBoundary, type SolvedRoute, Topology, TopologyError, VIA_GRAPH_SOLVER_DEFAULTS, type ValidateOpts, type ViaByNet, type ViaData, ViaGraphSolver, type ViaGraphWithConnections, type ViaTile, type ViaTileRecommendation, type ViaTileRecommendationCandidate, type ViaTileRecommendationProblemInput, type XYConnection, applyTransformToGraph, calculateGraphBounds, convertConnectionsToSerializedConnections, convertHyperGraphToSerializedHyperGraph, createBlankHyperGraph, createConvexViaGraphFromXYConnections, createGraphWithConnectionsFromBaseGraph, createViaGraphWithConnections, extractSectionOfHyperGraph, generateConvexViaTopologyRegions, generateDefaultViaTopologyRegions, generateJumperGrid, generateJumperX4Grid, generateViaTopologyRegions, pruneDeadEndPorts, reattachSectionToGraph, recommendViaTileFromGraphInput, rotateGraph90Degrees, viaTile4Regions as viaTile };
|
package/dist/index.js
CHANGED
|
@@ -1497,6 +1497,320 @@ var convertHyperGraphToSerializedHyperGraph = (graph) => {
|
|
|
1497
1497
|
};
|
|
1498
1498
|
};
|
|
1499
1499
|
|
|
1500
|
+
// lib/convertSerializedHyperGraphToHyperGraph.ts
|
|
1501
|
+
var convertSerializedHyperGraphToHyperGraph = (inputGraph) => {
|
|
1502
|
+
if (inputGraph.ports.length > 0 && "region1" in inputGraph.ports[0] && typeof inputGraph.ports[0].region1 === "object") {
|
|
1503
|
+
return inputGraph;
|
|
1504
|
+
}
|
|
1505
|
+
const portMap = /* @__PURE__ */ new Map();
|
|
1506
|
+
const regionMap = /* @__PURE__ */ new Map();
|
|
1507
|
+
for (const region of inputGraph.regions) {
|
|
1508
|
+
const { assignments: _, ...regionWithoutAssignments } = region;
|
|
1509
|
+
regionMap.set(region.regionId, {
|
|
1510
|
+
...regionWithoutAssignments,
|
|
1511
|
+
d: regionWithoutAssignments.d ? structuredClone(regionWithoutAssignments.d) : regionWithoutAssignments.d,
|
|
1512
|
+
ports: [],
|
|
1513
|
+
assignments: void 0
|
|
1514
|
+
});
|
|
1515
|
+
}
|
|
1516
|
+
for (const port of inputGraph.ports) {
|
|
1517
|
+
const region1 = regionMap.get(port.region1Id ?? port.region1?.regionId);
|
|
1518
|
+
const region2 = regionMap.get(port.region2Id ?? port.region2?.regionId);
|
|
1519
|
+
const deserializedPort = {
|
|
1520
|
+
portId: port.portId,
|
|
1521
|
+
region1,
|
|
1522
|
+
region2,
|
|
1523
|
+
d: port.d
|
|
1524
|
+
};
|
|
1525
|
+
portMap.set(port.portId, deserializedPort);
|
|
1526
|
+
region1.ports.push(deserializedPort);
|
|
1527
|
+
region2.ports.push(deserializedPort);
|
|
1528
|
+
}
|
|
1529
|
+
return {
|
|
1530
|
+
ports: Array.from(portMap.values()),
|
|
1531
|
+
regions: Array.from(regionMap.values())
|
|
1532
|
+
};
|
|
1533
|
+
};
|
|
1534
|
+
|
|
1535
|
+
// lib/convertSerializedConnectionsToConnections.ts
|
|
1536
|
+
var convertSerializedConnectionsToConnections = (inputConnections, graph) => {
|
|
1537
|
+
const connections = [];
|
|
1538
|
+
for (const inputConn of inputConnections) {
|
|
1539
|
+
if ("startRegionId" in inputConn) {
|
|
1540
|
+
connections.push({
|
|
1541
|
+
connectionId: inputConn.connectionId,
|
|
1542
|
+
mutuallyConnectedNetworkId: inputConn.mutuallyConnectedNetworkId ?? inputConn.connectionId,
|
|
1543
|
+
startRegion: graph.regions.find(
|
|
1544
|
+
(region) => region.regionId === inputConn.startRegionId
|
|
1545
|
+
),
|
|
1546
|
+
endRegion: graph.regions.find(
|
|
1547
|
+
(region) => region.regionId === inputConn.endRegionId
|
|
1548
|
+
)
|
|
1549
|
+
});
|
|
1550
|
+
} else {
|
|
1551
|
+
connections.push(inputConn);
|
|
1552
|
+
}
|
|
1553
|
+
}
|
|
1554
|
+
return connections;
|
|
1555
|
+
};
|
|
1556
|
+
|
|
1557
|
+
// lib/convertSerializedSolvedRoutesToSolvedRoutes.ts
|
|
1558
|
+
var convertSerializedSolvedRoutesToSolvedRoutes = (inputSolvedRoutes, graph) => {
|
|
1559
|
+
const portMap = new Map(graph.ports.map((port) => [port.portId, port]));
|
|
1560
|
+
const regionMap = new Map(
|
|
1561
|
+
graph.regions.map((region) => [region.regionId, region])
|
|
1562
|
+
);
|
|
1563
|
+
const connectionMap = new Map(
|
|
1564
|
+
convertSerializedConnectionsToConnections(
|
|
1565
|
+
inputSolvedRoutes.map((route) => route.connection),
|
|
1566
|
+
graph
|
|
1567
|
+
).map((connection) => [connection.connectionId, connection])
|
|
1568
|
+
);
|
|
1569
|
+
return inputSolvedRoutes.map((inputSolvedRoute) => {
|
|
1570
|
+
const path = [];
|
|
1571
|
+
for (const originalCandidate of inputSolvedRoute.path) {
|
|
1572
|
+
const port = portMap.get(originalCandidate.portId);
|
|
1573
|
+
if (!port) {
|
|
1574
|
+
throw new Error(
|
|
1575
|
+
`Port ${originalCandidate.portId} not found while deserializing solved route ${inputSolvedRoute.connection.connectionId}`
|
|
1576
|
+
);
|
|
1577
|
+
}
|
|
1578
|
+
const candidate = {
|
|
1579
|
+
port,
|
|
1580
|
+
g: originalCandidate.g,
|
|
1581
|
+
h: originalCandidate.h,
|
|
1582
|
+
f: originalCandidate.f,
|
|
1583
|
+
hops: originalCandidate.hops,
|
|
1584
|
+
ripRequired: originalCandidate.ripRequired
|
|
1585
|
+
};
|
|
1586
|
+
if (originalCandidate.lastPortId) {
|
|
1587
|
+
candidate.lastPort = getRequiredPort(
|
|
1588
|
+
portMap,
|
|
1589
|
+
originalCandidate.lastPortId,
|
|
1590
|
+
inputSolvedRoute.connection.connectionId
|
|
1591
|
+
);
|
|
1592
|
+
}
|
|
1593
|
+
if (originalCandidate.lastRegionId) {
|
|
1594
|
+
candidate.lastRegion = getRequiredRegion(
|
|
1595
|
+
regionMap,
|
|
1596
|
+
originalCandidate.lastRegionId,
|
|
1597
|
+
inputSolvedRoute.connection.connectionId
|
|
1598
|
+
);
|
|
1599
|
+
}
|
|
1600
|
+
if (originalCandidate.nextRegionId) {
|
|
1601
|
+
candidate.nextRegion = getRequiredRegion(
|
|
1602
|
+
regionMap,
|
|
1603
|
+
originalCandidate.nextRegionId,
|
|
1604
|
+
inputSolvedRoute.connection.connectionId
|
|
1605
|
+
);
|
|
1606
|
+
}
|
|
1607
|
+
const parent = path[path.length - 1];
|
|
1608
|
+
if (parent) candidate.parent = parent;
|
|
1609
|
+
path.push(candidate);
|
|
1610
|
+
}
|
|
1611
|
+
const connection = connectionMap.get(
|
|
1612
|
+
inputSolvedRoute.connection.connectionId
|
|
1613
|
+
);
|
|
1614
|
+
if (!connection) {
|
|
1615
|
+
throw new Error(
|
|
1616
|
+
`Connection ${inputSolvedRoute.connection.connectionId} not found while deserializing solved route`
|
|
1617
|
+
);
|
|
1618
|
+
}
|
|
1619
|
+
return {
|
|
1620
|
+
path,
|
|
1621
|
+
connection,
|
|
1622
|
+
requiredRip: inputSolvedRoute.requiredRip
|
|
1623
|
+
};
|
|
1624
|
+
});
|
|
1625
|
+
};
|
|
1626
|
+
var getRequiredPort = (portMap, portId, connectionId) => {
|
|
1627
|
+
const port = portMap.get(portId);
|
|
1628
|
+
if (!port) {
|
|
1629
|
+
throw new Error(
|
|
1630
|
+
`Port ${portId} not found while deserializing solved route ${connectionId}`
|
|
1631
|
+
);
|
|
1632
|
+
}
|
|
1633
|
+
return port;
|
|
1634
|
+
};
|
|
1635
|
+
var getRequiredRegion = (regionMap, regionId, connectionId) => {
|
|
1636
|
+
const region = regionMap.get(regionId);
|
|
1637
|
+
if (!region) {
|
|
1638
|
+
throw new Error(
|
|
1639
|
+
`Region ${regionId} not found while deserializing solved route ${connectionId}`
|
|
1640
|
+
);
|
|
1641
|
+
}
|
|
1642
|
+
return region;
|
|
1643
|
+
};
|
|
1644
|
+
|
|
1645
|
+
// lib/createBlankHyperGraph.ts
|
|
1646
|
+
var createBlankHyperGraph = (inputGraph) => {
|
|
1647
|
+
const deserializedGraph = convertSerializedHyperGraphToHyperGraph(inputGraph);
|
|
1648
|
+
if (!inputGraph.solvedRoutes) {
|
|
1649
|
+
throw new Error(
|
|
1650
|
+
"createBlankHyperGraph requires graph.solvedRoutes to be present"
|
|
1651
|
+
);
|
|
1652
|
+
}
|
|
1653
|
+
const solvedRoutes = convertSerializedSolvedRoutesToSolvedRoutes(
|
|
1654
|
+
inputGraph.solvedRoutes,
|
|
1655
|
+
deserializedGraph
|
|
1656
|
+
);
|
|
1657
|
+
const removableLeafRegionIds = getRemovableLeafRegionIds(deserializedGraph);
|
|
1658
|
+
const replacedEndpointRegionIds = getReplacedEndpointRegionIds(solvedRoutes);
|
|
1659
|
+
const blankGraph = cloneGraphExcludingRegions(
|
|
1660
|
+
deserializedGraph,
|
|
1661
|
+
removableLeafRegionIds
|
|
1662
|
+
);
|
|
1663
|
+
const connections = [];
|
|
1664
|
+
for (const solvedRoute of solvedRoutes) {
|
|
1665
|
+
const startRegion = getBlankConnectionEndpointRegion({
|
|
1666
|
+
solvedRoute,
|
|
1667
|
+
blankGraph,
|
|
1668
|
+
replacedEndpointRegionIds,
|
|
1669
|
+
endpoint: "start"
|
|
1670
|
+
});
|
|
1671
|
+
const endRegion = getBlankConnectionEndpointRegion({
|
|
1672
|
+
solvedRoute,
|
|
1673
|
+
blankGraph,
|
|
1674
|
+
replacedEndpointRegionIds,
|
|
1675
|
+
endpoint: "end"
|
|
1676
|
+
});
|
|
1677
|
+
connections.push({
|
|
1678
|
+
connectionId: solvedRoute.connection.connectionId,
|
|
1679
|
+
mutuallyConnectedNetworkId: solvedRoute.connection.mutuallyConnectedNetworkId,
|
|
1680
|
+
startRegion,
|
|
1681
|
+
endRegion
|
|
1682
|
+
});
|
|
1683
|
+
}
|
|
1684
|
+
return {
|
|
1685
|
+
...convertHyperGraphToSerializedHyperGraph(blankGraph),
|
|
1686
|
+
connections: convertConnectionsToSerializedConnections(connections),
|
|
1687
|
+
_sectionCentralRegionId: inputGraph._sectionCentralRegionId,
|
|
1688
|
+
_sectionRouteBindings: inputGraph._sectionRouteBindings ? structuredClone(inputGraph._sectionRouteBindings) : void 0
|
|
1689
|
+
};
|
|
1690
|
+
};
|
|
1691
|
+
var getRemovableLeafRegionIds = (graph) => {
|
|
1692
|
+
return new Set(
|
|
1693
|
+
graph.regions.filter((region) => region.ports.length === 1).map((region) => region.regionId)
|
|
1694
|
+
);
|
|
1695
|
+
};
|
|
1696
|
+
var getReplacedEndpointRegionIds = (solvedRoutes) => {
|
|
1697
|
+
const replacedEndpointRegionIds = /* @__PURE__ */ new Set();
|
|
1698
|
+
for (const solvedRoute of solvedRoutes) {
|
|
1699
|
+
const startCandidate = solvedRoute.path[0];
|
|
1700
|
+
if (startCandidate && shouldReplaceEndpointRegion(
|
|
1701
|
+
solvedRoute.connection.startRegion,
|
|
1702
|
+
startCandidate
|
|
1703
|
+
)) {
|
|
1704
|
+
replacedEndpointRegionIds.add(solvedRoute.connection.startRegion.regionId);
|
|
1705
|
+
}
|
|
1706
|
+
const endCandidate = solvedRoute.path[solvedRoute.path.length - 1];
|
|
1707
|
+
if (endCandidate && shouldReplaceEndpointRegion(
|
|
1708
|
+
solvedRoute.connection.endRegion,
|
|
1709
|
+
endCandidate
|
|
1710
|
+
)) {
|
|
1711
|
+
replacedEndpointRegionIds.add(solvedRoute.connection.endRegion.regionId);
|
|
1712
|
+
}
|
|
1713
|
+
}
|
|
1714
|
+
return replacedEndpointRegionIds;
|
|
1715
|
+
};
|
|
1716
|
+
var shouldReplaceEndpointRegion = (endpointRegion, endpointCandidate) => {
|
|
1717
|
+
return endpointRegion.ports.length === 1 && endpointRegion.ports[0]?.portId === endpointCandidate.port.portId;
|
|
1718
|
+
};
|
|
1719
|
+
var cloneGraphExcludingRegions = (graph, excludedRegionIds) => {
|
|
1720
|
+
const clonedRegionMap = /* @__PURE__ */ new Map();
|
|
1721
|
+
const clonedPorts = [];
|
|
1722
|
+
for (const region of graph.regions) {
|
|
1723
|
+
if (excludedRegionIds.has(region.regionId)) continue;
|
|
1724
|
+
clonedRegionMap.set(region.regionId, {
|
|
1725
|
+
regionId: region.regionId,
|
|
1726
|
+
ports: [],
|
|
1727
|
+
d: region.d ? structuredClone(region.d) : region.d,
|
|
1728
|
+
assignments: []
|
|
1729
|
+
});
|
|
1730
|
+
}
|
|
1731
|
+
for (const port of graph.ports) {
|
|
1732
|
+
if (excludedRegionIds.has(port.region1.regionId) || excludedRegionIds.has(port.region2.regionId)) {
|
|
1733
|
+
continue;
|
|
1734
|
+
}
|
|
1735
|
+
const clonedPort = {
|
|
1736
|
+
portId: port.portId,
|
|
1737
|
+
region1: clonedRegionMap.get(port.region1.regionId),
|
|
1738
|
+
region2: clonedRegionMap.get(port.region2.regionId),
|
|
1739
|
+
d: port.d ? structuredClone(port.d) : port.d
|
|
1740
|
+
};
|
|
1741
|
+
clonedPort.region1.ports.push(clonedPort);
|
|
1742
|
+
clonedPort.region2.ports.push(clonedPort);
|
|
1743
|
+
clonedPorts.push(clonedPort);
|
|
1744
|
+
}
|
|
1745
|
+
return {
|
|
1746
|
+
regions: Array.from(clonedRegionMap.values()),
|
|
1747
|
+
ports: clonedPorts
|
|
1748
|
+
};
|
|
1749
|
+
};
|
|
1750
|
+
var getBlankConnectionEndpointRegion = (input) => {
|
|
1751
|
+
const { solvedRoute, blankGraph, replacedEndpointRegionIds, endpoint } = input;
|
|
1752
|
+
const originalRegion = endpoint === "start" ? solvedRoute.connection.startRegion : solvedRoute.connection.endRegion;
|
|
1753
|
+
const existingRegion = blankGraph.regions.find(
|
|
1754
|
+
(region) => region.regionId === originalRegion.regionId
|
|
1755
|
+
);
|
|
1756
|
+
if (existingRegion) return existingRegion;
|
|
1757
|
+
if (!replacedEndpointRegionIds.has(originalRegion.regionId)) {
|
|
1758
|
+
throw new Error(
|
|
1759
|
+
`Connection endpoint region ${originalRegion.regionId} is missing from blank graph`
|
|
1760
|
+
);
|
|
1761
|
+
}
|
|
1762
|
+
const endpointCandidate = endpoint === "start" ? solvedRoute.path[0] : solvedRoute.path[solvedRoute.path.length - 1];
|
|
1763
|
+
if (!endpointCandidate) {
|
|
1764
|
+
throw new Error(
|
|
1765
|
+
`Solved route ${solvedRoute.connection.connectionId} has no path candidates`
|
|
1766
|
+
);
|
|
1767
|
+
}
|
|
1768
|
+
const attachedRegionId = getAttachedRegionId({
|
|
1769
|
+
port: endpointCandidate.port,
|
|
1770
|
+
originalRegionId: originalRegion.regionId,
|
|
1771
|
+
preferredRegionId: endpoint === "start" ? endpointCandidate.nextRegion?.regionId : endpointCandidate.lastRegion?.regionId
|
|
1772
|
+
});
|
|
1773
|
+
if (!attachedRegionId) {
|
|
1774
|
+
throw new Error(
|
|
1775
|
+
`Could not determine ${endpoint} region for connection ${solvedRoute.connection.connectionId}`
|
|
1776
|
+
);
|
|
1777
|
+
}
|
|
1778
|
+
const attachedRegion = blankGraph.regions.find(
|
|
1779
|
+
(region) => region.regionId === attachedRegionId
|
|
1780
|
+
);
|
|
1781
|
+
if (!attachedRegion) {
|
|
1782
|
+
throw new Error(
|
|
1783
|
+
`Region ${attachedRegionId} not found in blank graph for connection ${solvedRoute.connection.connectionId}`
|
|
1784
|
+
);
|
|
1785
|
+
}
|
|
1786
|
+
const connectionRegion = {
|
|
1787
|
+
regionId: `connection:${solvedRoute.connection.connectionId}:${endpoint}`,
|
|
1788
|
+
ports: [],
|
|
1789
|
+
d: originalRegion.d ? structuredClone(originalRegion.d) : originalRegion.d,
|
|
1790
|
+
assignments: []
|
|
1791
|
+
};
|
|
1792
|
+
blankGraph.regions.push(connectionRegion);
|
|
1793
|
+
const connectionPort = {
|
|
1794
|
+
portId: `connection:${solvedRoute.connection.connectionId}:${endpoint}-port`,
|
|
1795
|
+
region1: connectionRegion,
|
|
1796
|
+
region2: attachedRegion,
|
|
1797
|
+
d: endpointCandidate.port.d ? structuredClone(endpointCandidate.port.d) : endpointCandidate.port.d
|
|
1798
|
+
};
|
|
1799
|
+
connectionRegion.ports.push(connectionPort);
|
|
1800
|
+
attachedRegion.ports.push(connectionPort);
|
|
1801
|
+
blankGraph.ports.push(connectionPort);
|
|
1802
|
+
return connectionRegion;
|
|
1803
|
+
};
|
|
1804
|
+
var getAttachedRegionId = (input) => {
|
|
1805
|
+
const { port, originalRegionId, preferredRegionId } = input;
|
|
1806
|
+
if (preferredRegionId && preferredRegionId !== originalRegionId) {
|
|
1807
|
+
return preferredRegionId;
|
|
1808
|
+
}
|
|
1809
|
+
if (port.region1.regionId !== originalRegionId) return port.region1.regionId;
|
|
1810
|
+
if (port.region2.regionId !== originalRegionId) return port.region2.regionId;
|
|
1811
|
+
return void 0;
|
|
1812
|
+
};
|
|
1813
|
+
|
|
1500
1814
|
// lib/HyperGraphSectionOptimizer/getOrCreateBoundaryRegion.ts
|
|
1501
1815
|
var getOrCreateBoundaryRegion = ({
|
|
1502
1816
|
port,
|
|
@@ -1656,14 +1970,30 @@ var getSectionOfHyperGraphAsHyperGraph = (input) => {
|
|
|
1656
1970
|
};
|
|
1657
1971
|
const sectionRoutes = [];
|
|
1658
1972
|
const sectionConnections = [];
|
|
1973
|
+
const sectionRouteSegments = [];
|
|
1974
|
+
for (const solvedRoute of solvedRoutes) {
|
|
1975
|
+
const routePathSegment = getRouteSectionSpan(solvedRoute, sectionRegionIds);
|
|
1976
|
+
if (!routePathSegment) continue;
|
|
1977
|
+
const startCandidate = solvedRoute.path[routePathSegment.startIndex];
|
|
1978
|
+
const endCandidate = solvedRoute.path[routePathSegment.endIndex];
|
|
1979
|
+
sectionRouteSegments.push({
|
|
1980
|
+
solvedRoute,
|
|
1981
|
+
solvedPathStartIndex: routePathSegment.startIndex,
|
|
1982
|
+
solvedPathEndIndex: routePathSegment.endIndex,
|
|
1983
|
+
startCandidate,
|
|
1984
|
+
endCandidate
|
|
1985
|
+
});
|
|
1986
|
+
}
|
|
1659
1987
|
const sectionRegionMap = new Map(
|
|
1660
1988
|
sectionGraph.regions.map((region) => [region.regionId, region])
|
|
1661
1989
|
);
|
|
1662
|
-
for (const
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1990
|
+
for (const {
|
|
1991
|
+
solvedRoute,
|
|
1992
|
+
solvedPathStartIndex,
|
|
1993
|
+
solvedPathEndIndex,
|
|
1994
|
+
startCandidate,
|
|
1995
|
+
endCandidate
|
|
1996
|
+
} of sectionRouteSegments) {
|
|
1667
1997
|
let startRegionId;
|
|
1668
1998
|
let startRegion;
|
|
1669
1999
|
if (sectionRegionIds.has(solvedRoute.connection.startRegion.regionId)) {
|
|
@@ -1707,213 +2037,71 @@ var getSectionOfHyperGraphAsHyperGraph = (input) => {
|
|
|
1707
2037
|
console.error(
|
|
1708
2038
|
` Original startRegion: ${solvedRoute.connection.startRegion.regionId}`
|
|
1709
2039
|
);
|
|
1710
|
-
console.error(` startCandidate port: ${startCandidate.port.portId}`);
|
|
1711
|
-
console.error(
|
|
1712
|
-
` Available regions in sectionRegionMap:`,
|
|
1713
|
-
Array.from(sectionRegionMap.keys())
|
|
1714
|
-
);
|
|
1715
|
-
throw new Error(
|
|
1716
|
-
`startRegion ${startRegionId} not found in sectionRegionMap`
|
|
1717
|
-
);
|
|
1718
|
-
}
|
|
1719
|
-
if (!endRegion) {
|
|
1720
|
-
console.error(
|
|
1721
|
-
`[getSectionOfHyperGraphAsHyperGraph] CRITICAL ERROR: endRegion not found!`
|
|
1722
|
-
);
|
|
1723
|
-
console.error(` Looking for: ${endRegionId}`);
|
|
1724
|
-
console.error(
|
|
1725
|
-
` Route connection: ${solvedRoute.connection.connectionId}`
|
|
1726
|
-
);
|
|
1727
|
-
console.error(
|
|
1728
|
-
` Original endRegion: ${solvedRoute.connection.endRegion.regionId}`
|
|
1729
|
-
);
|
|
1730
|
-
console.error(` endCandidate port: ${endCandidate.port.portId}`);
|
|
1731
|
-
console.error(
|
|
1732
|
-
` Available regions in sectionRegionMap:`,
|
|
1733
|
-
Array.from(sectionRegionMap.keys())
|
|
1734
|
-
);
|
|
1735
|
-
throw new Error(`endRegion ${endRegionId} not found in sectionRegionMap`);
|
|
1736
|
-
}
|
|
1737
|
-
const sectionConnection = {
|
|
1738
|
-
connectionId: solvedRoute.connection.connectionId,
|
|
1739
|
-
mutuallyConnectedNetworkId: solvedRoute.connection.mutuallyConnectedNetworkId,
|
|
1740
|
-
startRegion,
|
|
1741
|
-
endRegion
|
|
1742
|
-
};
|
|
1743
|
-
const rawPath = solvedRoute.path.slice(span.startIndex, span.endIndex + 1);
|
|
1744
|
-
const sectionRouteBase = {
|
|
1745
|
-
globalRoute: solvedRoute,
|
|
1746
|
-
globalConnection: solvedRoute.connection,
|
|
1747
|
-
sectionConnection,
|
|
1748
|
-
sectionStartIndex: span.startIndex,
|
|
1749
|
-
sectionEndIndex: span.endIndex
|
|
1750
|
-
};
|
|
1751
|
-
sectionRoutes.push({
|
|
1752
|
-
...sectionRouteBase,
|
|
1753
|
-
canRemainFixedInSectionSolve: rawPath.every(
|
|
1754
|
-
(candidate) => sectionGraph.ports.some(
|
|
1755
|
-
(port) => port.portId === candidate.port.portId
|
|
1756
|
-
)
|
|
1757
|
-
),
|
|
1758
|
-
sectionRoute: sliceSolvedRouteIntoLocalSection({
|
|
1759
|
-
sectionRoute: sectionRouteBase,
|
|
1760
|
-
graph: sectionGraph
|
|
1761
|
-
})
|
|
1762
|
-
});
|
|
1763
|
-
sectionConnections.push(sectionConnection);
|
|
1764
|
-
}
|
|
1765
|
-
return {
|
|
1766
|
-
centralRegionId: centralRegion.regionId,
|
|
1767
|
-
sectionRegionIds,
|
|
1768
|
-
graph: sectionGraph,
|
|
1769
|
-
connections: sectionConnections,
|
|
1770
|
-
sectionRoutes
|
|
1771
|
-
};
|
|
1772
|
-
};
|
|
1773
|
-
|
|
1774
|
-
// lib/convertSerializedHyperGraphToHyperGraph.ts
|
|
1775
|
-
var convertSerializedHyperGraphToHyperGraph = (inputGraph) => {
|
|
1776
|
-
if (inputGraph.ports.length > 0 && "region1" in inputGraph.ports[0] && typeof inputGraph.ports[0].region1 === "object") {
|
|
1777
|
-
return inputGraph;
|
|
1778
|
-
}
|
|
1779
|
-
const portMap = /* @__PURE__ */ new Map();
|
|
1780
|
-
const regionMap = /* @__PURE__ */ new Map();
|
|
1781
|
-
for (const region of inputGraph.regions) {
|
|
1782
|
-
const { assignments: _, ...regionWithoutAssignments } = region;
|
|
1783
|
-
regionMap.set(region.regionId, {
|
|
1784
|
-
...regionWithoutAssignments,
|
|
1785
|
-
d: regionWithoutAssignments.d ? structuredClone(regionWithoutAssignments.d) : regionWithoutAssignments.d,
|
|
1786
|
-
ports: [],
|
|
1787
|
-
assignments: void 0
|
|
1788
|
-
});
|
|
1789
|
-
}
|
|
1790
|
-
for (const port of inputGraph.ports) {
|
|
1791
|
-
const region1 = regionMap.get(port.region1Id ?? port.region1?.regionId);
|
|
1792
|
-
const region2 = regionMap.get(port.region2Id ?? port.region2?.regionId);
|
|
1793
|
-
const deserializedPort = {
|
|
1794
|
-
portId: port.portId,
|
|
1795
|
-
region1,
|
|
1796
|
-
region2,
|
|
1797
|
-
d: port.d
|
|
1798
|
-
};
|
|
1799
|
-
portMap.set(port.portId, deserializedPort);
|
|
1800
|
-
region1.ports.push(deserializedPort);
|
|
1801
|
-
region2.ports.push(deserializedPort);
|
|
1802
|
-
}
|
|
1803
|
-
return {
|
|
1804
|
-
ports: Array.from(portMap.values()),
|
|
1805
|
-
regions: Array.from(regionMap.values())
|
|
1806
|
-
};
|
|
1807
|
-
};
|
|
1808
|
-
|
|
1809
|
-
// lib/convertSerializedConnectionsToConnections.ts
|
|
1810
|
-
var convertSerializedConnectionsToConnections = (inputConnections, graph) => {
|
|
1811
|
-
const connections = [];
|
|
1812
|
-
for (const inputConn of inputConnections) {
|
|
1813
|
-
if ("startRegionId" in inputConn) {
|
|
1814
|
-
connections.push({
|
|
1815
|
-
connectionId: inputConn.connectionId,
|
|
1816
|
-
mutuallyConnectedNetworkId: inputConn.mutuallyConnectedNetworkId ?? inputConn.connectionId,
|
|
1817
|
-
startRegion: graph.regions.find(
|
|
1818
|
-
(region) => region.regionId === inputConn.startRegionId
|
|
1819
|
-
),
|
|
1820
|
-
endRegion: graph.regions.find(
|
|
1821
|
-
(region) => region.regionId === inputConn.endRegionId
|
|
1822
|
-
)
|
|
1823
|
-
});
|
|
1824
|
-
} else {
|
|
1825
|
-
connections.push(inputConn);
|
|
1826
|
-
}
|
|
1827
|
-
}
|
|
1828
|
-
return connections;
|
|
1829
|
-
};
|
|
1830
|
-
|
|
1831
|
-
// lib/convertSerializedSolvedRoutesToSolvedRoutes.ts
|
|
1832
|
-
var convertSerializedSolvedRoutesToSolvedRoutes = (inputSolvedRoutes, graph) => {
|
|
1833
|
-
const portMap = new Map(graph.ports.map((port) => [port.portId, port]));
|
|
1834
|
-
const regionMap = new Map(
|
|
1835
|
-
graph.regions.map((region) => [region.regionId, region])
|
|
1836
|
-
);
|
|
1837
|
-
const connectionMap = new Map(
|
|
1838
|
-
convertSerializedConnectionsToConnections(
|
|
1839
|
-
inputSolvedRoutes.map((route) => route.connection),
|
|
1840
|
-
graph
|
|
1841
|
-
).map((connection) => [connection.connectionId, connection])
|
|
1842
|
-
);
|
|
1843
|
-
return inputSolvedRoutes.map((inputSolvedRoute) => {
|
|
1844
|
-
const path = [];
|
|
1845
|
-
for (const originalCandidate of inputSolvedRoute.path) {
|
|
1846
|
-
const port = portMap.get(originalCandidate.portId);
|
|
1847
|
-
if (!port) {
|
|
1848
|
-
throw new Error(
|
|
1849
|
-
`Port ${originalCandidate.portId} not found while deserializing solved route ${inputSolvedRoute.connection.connectionId}`
|
|
1850
|
-
);
|
|
1851
|
-
}
|
|
1852
|
-
const candidate = {
|
|
1853
|
-
port,
|
|
1854
|
-
g: originalCandidate.g,
|
|
1855
|
-
h: originalCandidate.h,
|
|
1856
|
-
f: originalCandidate.f,
|
|
1857
|
-
hops: originalCandidate.hops,
|
|
1858
|
-
ripRequired: originalCandidate.ripRequired
|
|
1859
|
-
};
|
|
1860
|
-
if (originalCandidate.lastPortId) {
|
|
1861
|
-
candidate.lastPort = getRequiredPort(
|
|
1862
|
-
portMap,
|
|
1863
|
-
originalCandidate.lastPortId,
|
|
1864
|
-
inputSolvedRoute.connection.connectionId
|
|
1865
|
-
);
|
|
1866
|
-
}
|
|
1867
|
-
if (originalCandidate.lastRegionId) {
|
|
1868
|
-
candidate.lastRegion = getRequiredRegion(
|
|
1869
|
-
regionMap,
|
|
1870
|
-
originalCandidate.lastRegionId,
|
|
1871
|
-
inputSolvedRoute.connection.connectionId
|
|
1872
|
-
);
|
|
1873
|
-
}
|
|
1874
|
-
if (originalCandidate.nextRegionId) {
|
|
1875
|
-
candidate.nextRegion = getRequiredRegion(
|
|
1876
|
-
regionMap,
|
|
1877
|
-
originalCandidate.nextRegionId,
|
|
1878
|
-
inputSolvedRoute.connection.connectionId
|
|
1879
|
-
);
|
|
1880
|
-
}
|
|
1881
|
-
const parent = path[path.length - 1];
|
|
1882
|
-
if (parent) candidate.parent = parent;
|
|
1883
|
-
path.push(candidate);
|
|
1884
|
-
}
|
|
1885
|
-
const connection = connectionMap.get(
|
|
1886
|
-
inputSolvedRoute.connection.connectionId
|
|
1887
|
-
);
|
|
1888
|
-
if (!connection) {
|
|
2040
|
+
console.error(` startCandidate port: ${startCandidate.port.portId}`);
|
|
2041
|
+
console.error(
|
|
2042
|
+
` Available regions in sectionRegionMap:`,
|
|
2043
|
+
Array.from(sectionRegionMap.keys())
|
|
2044
|
+
);
|
|
1889
2045
|
throw new Error(
|
|
1890
|
-
`
|
|
2046
|
+
`startRegion ${startRegionId} not found in sectionRegionMap`
|
|
1891
2047
|
);
|
|
1892
2048
|
}
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
2049
|
+
if (!endRegion) {
|
|
2050
|
+
console.error(
|
|
2051
|
+
`[getSectionOfHyperGraphAsHyperGraph] CRITICAL ERROR: endRegion not found!`
|
|
2052
|
+
);
|
|
2053
|
+
console.error(` Looking for: ${endRegionId}`);
|
|
2054
|
+
console.error(
|
|
2055
|
+
` Route connection: ${solvedRoute.connection.connectionId}`
|
|
2056
|
+
);
|
|
2057
|
+
console.error(
|
|
2058
|
+
` Original endRegion: ${solvedRoute.connection.endRegion.regionId}`
|
|
2059
|
+
);
|
|
2060
|
+
console.error(` endCandidate port: ${endCandidate.port.portId}`);
|
|
2061
|
+
console.error(
|
|
2062
|
+
` Available regions in sectionRegionMap:`,
|
|
2063
|
+
Array.from(sectionRegionMap.keys())
|
|
2064
|
+
);
|
|
2065
|
+
throw new Error(`endRegion ${endRegionId} not found in sectionRegionMap`);
|
|
2066
|
+
}
|
|
2067
|
+
const sectionConnection = {
|
|
2068
|
+
connectionId: solvedRoute.connection.connectionId,
|
|
2069
|
+
mutuallyConnectedNetworkId: solvedRoute.connection.mutuallyConnectedNetworkId,
|
|
2070
|
+
startRegion,
|
|
2071
|
+
endRegion
|
|
1897
2072
|
};
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
const port = portMap.get(portId);
|
|
1902
|
-
if (!port) {
|
|
1903
|
-
throw new Error(
|
|
1904
|
-
`Port ${portId} not found while deserializing solved route ${connectionId}`
|
|
1905
|
-
);
|
|
1906
|
-
}
|
|
1907
|
-
return port;
|
|
1908
|
-
};
|
|
1909
|
-
var getRequiredRegion = (regionMap, regionId, connectionId) => {
|
|
1910
|
-
const region = regionMap.get(regionId);
|
|
1911
|
-
if (!region) {
|
|
1912
|
-
throw new Error(
|
|
1913
|
-
`Region ${regionId} not found while deserializing solved route ${connectionId}`
|
|
2073
|
+
const rawPath = solvedRoute.path.slice(
|
|
2074
|
+
solvedPathStartIndex,
|
|
2075
|
+
solvedPathEndIndex + 1
|
|
1914
2076
|
);
|
|
2077
|
+
const sectionRouteBase = {
|
|
2078
|
+
globalRoute: solvedRoute,
|
|
2079
|
+
globalConnection: solvedRoute.connection,
|
|
2080
|
+
sectionConnection,
|
|
2081
|
+
sectionStartIndex: solvedPathStartIndex,
|
|
2082
|
+
sectionEndIndex: solvedPathEndIndex
|
|
2083
|
+
};
|
|
2084
|
+
sectionRoutes.push({
|
|
2085
|
+
...sectionRouteBase,
|
|
2086
|
+
canRemainFixedInSectionSolve: rawPath.every(
|
|
2087
|
+
(candidate) => sectionGraph.ports.some(
|
|
2088
|
+
(port) => port.portId === candidate.port.portId
|
|
2089
|
+
)
|
|
2090
|
+
),
|
|
2091
|
+
sectionRoute: sliceSolvedRouteIntoLocalSection({
|
|
2092
|
+
sectionRoute: sectionRouteBase,
|
|
2093
|
+
graph: sectionGraph
|
|
2094
|
+
})
|
|
2095
|
+
});
|
|
2096
|
+
sectionConnections.push(sectionConnection);
|
|
1915
2097
|
}
|
|
1916
|
-
return
|
|
2098
|
+
return {
|
|
2099
|
+
centralRegionId: centralRegion.regionId,
|
|
2100
|
+
sectionRegionIds,
|
|
2101
|
+
graph: sectionGraph,
|
|
2102
|
+
connections: sectionConnections,
|
|
2103
|
+
sectionRoutes
|
|
2104
|
+
};
|
|
1917
2105
|
};
|
|
1918
2106
|
|
|
1919
2107
|
// lib/convertSolvedRoutesToSerializedSolvedRoutes.ts
|
|
@@ -1948,6 +2136,11 @@ var extractSectionOfHyperGraph = (input) => {
|
|
|
1948
2136
|
`Central region ${input.centralRegionId} not found in hypergraph`
|
|
1949
2137
|
);
|
|
1950
2138
|
}
|
|
2139
|
+
if (!input.graph.solvedRoutes) {
|
|
2140
|
+
throw new Error(
|
|
2141
|
+
"extractSectionOfHyperGraph requires graph.solvedRoutes to be present"
|
|
2142
|
+
);
|
|
2143
|
+
}
|
|
1951
2144
|
const solvedRoutes = convertSerializedSolvedRoutesToSolvedRoutes(
|
|
1952
2145
|
input.graph.solvedRoutes,
|
|
1953
2146
|
deserializedGraph
|
|
@@ -1960,9 +2153,16 @@ var extractSectionOfHyperGraph = (input) => {
|
|
|
1960
2153
|
});
|
|
1961
2154
|
return {
|
|
1962
2155
|
...convertHyperGraphToSerializedHyperGraph(section.graph),
|
|
2156
|
+
connections: convertConnectionsToSerializedConnections(section.connections),
|
|
1963
2157
|
solvedRoutes: convertSolvedRoutesToSerializedSolvedRoutes(
|
|
1964
2158
|
section.sectionRoutes.map((route) => route.sectionRoute)
|
|
1965
|
-
)
|
|
2159
|
+
),
|
|
2160
|
+
_sectionCentralRegionId: section.centralRegionId,
|
|
2161
|
+
_sectionRouteBindings: section.sectionRoutes.map((route) => ({
|
|
2162
|
+
connectionId: route.globalConnection.connectionId,
|
|
2163
|
+
solvedPathStartIndex: route.sectionStartIndex,
|
|
2164
|
+
solvedPathEndIndex: route.sectionEndIndex
|
|
2165
|
+
}))
|
|
1966
2166
|
};
|
|
1967
2167
|
};
|
|
1968
2168
|
|
|
@@ -2575,6 +2775,118 @@ var HyperGraphSolver = class extends BaseSolver {
|
|
|
2575
2775
|
}
|
|
2576
2776
|
};
|
|
2577
2777
|
|
|
2778
|
+
// lib/reattachSectionToGraph.ts
|
|
2779
|
+
var reattachSectionToGraph = (input) => {
|
|
2780
|
+
const { fullGraph, solvedSectionGraph } = input;
|
|
2781
|
+
if (!fullGraph.solvedRoutes) {
|
|
2782
|
+
throw new Error("reattachSectionToGraph requires fullGraph.solvedRoutes");
|
|
2783
|
+
}
|
|
2784
|
+
if (!solvedSectionGraph.solvedRoutes) {
|
|
2785
|
+
throw new Error(
|
|
2786
|
+
"reattachSectionToGraph requires solvedSectionGraph.solvedRoutes"
|
|
2787
|
+
);
|
|
2788
|
+
}
|
|
2789
|
+
if (!solvedSectionGraph._sectionRouteBindings) {
|
|
2790
|
+
throw new Error(
|
|
2791
|
+
"reattachSectionToGraph requires solvedSectionGraph._sectionRouteBindings"
|
|
2792
|
+
);
|
|
2793
|
+
}
|
|
2794
|
+
const bindingByConnectionId = new Map(
|
|
2795
|
+
solvedSectionGraph._sectionRouteBindings.map((binding) => [
|
|
2796
|
+
binding.connectionId,
|
|
2797
|
+
binding
|
|
2798
|
+
])
|
|
2799
|
+
);
|
|
2800
|
+
const replacementByConnectionId = new Map(
|
|
2801
|
+
solvedSectionGraph.solvedRoutes.map((route) => [
|
|
2802
|
+
route.connection.connectionId,
|
|
2803
|
+
route
|
|
2804
|
+
])
|
|
2805
|
+
);
|
|
2806
|
+
return {
|
|
2807
|
+
...fullGraph,
|
|
2808
|
+
solvedRoutes: fullGraph.solvedRoutes.map((fullSolvedRoute) => {
|
|
2809
|
+
const binding = bindingByConnectionId.get(
|
|
2810
|
+
fullSolvedRoute.connection.connectionId
|
|
2811
|
+
);
|
|
2812
|
+
if (!binding) return fullSolvedRoute;
|
|
2813
|
+
const replacementSolvedRoute = replacementByConnectionId.get(
|
|
2814
|
+
fullSolvedRoute.connection.connectionId
|
|
2815
|
+
);
|
|
2816
|
+
if (!replacementSolvedRoute) return fullSolvedRoute;
|
|
2817
|
+
const replacementInteriorPath = replacementSolvedRoute.path.slice(1, -1);
|
|
2818
|
+
const replacementPath = binding.solvedPathStartIndex === binding.solvedPathEndIndex ? [fullSolvedRoute.path[binding.solvedPathStartIndex]] : [
|
|
2819
|
+
fullSolvedRoute.path[binding.solvedPathStartIndex],
|
|
2820
|
+
...replacementInteriorPath.map((candidate) => ({
|
|
2821
|
+
...candidate
|
|
2822
|
+
})),
|
|
2823
|
+
fullSolvedRoute.path[binding.solvedPathEndIndex]
|
|
2824
|
+
];
|
|
2825
|
+
return {
|
|
2826
|
+
connection: fullSolvedRoute.connection,
|
|
2827
|
+
requiredRip: fullSolvedRoute.requiredRip || replacementSolvedRoute.requiredRip,
|
|
2828
|
+
path: normalizeSerializedPath(
|
|
2829
|
+
[
|
|
2830
|
+
...fullSolvedRoute.path.slice(0, binding.solvedPathStartIndex),
|
|
2831
|
+
...replacementPath.map((candidate) => ({
|
|
2832
|
+
...candidate
|
|
2833
|
+
})),
|
|
2834
|
+
...fullSolvedRoute.path.slice(binding.solvedPathEndIndex + 1)
|
|
2835
|
+
],
|
|
2836
|
+
fullGraph
|
|
2837
|
+
)
|
|
2838
|
+
};
|
|
2839
|
+
})
|
|
2840
|
+
};
|
|
2841
|
+
};
|
|
2842
|
+
var normalizeSerializedPath = (path, graph) => {
|
|
2843
|
+
const portMap = new Map(graph.ports.map((port) => [port.portId, port]));
|
|
2844
|
+
return path.map((candidate, index) => {
|
|
2845
|
+
const previousCandidate = index > 0 ? path[index - 1] : void 0;
|
|
2846
|
+
const nextCandidate = index < path.length - 1 ? path[index + 1] : void 0;
|
|
2847
|
+
return {
|
|
2848
|
+
...candidate,
|
|
2849
|
+
hops: index,
|
|
2850
|
+
lastPortId: previousCandidate?.portId,
|
|
2851
|
+
lastRegionId: previousCandidate ? getSharedRegionId(portMap, previousCandidate.portId, candidate.portId) : void 0,
|
|
2852
|
+
nextRegionId: nextCandidate ? getSharedRegionId(portMap, candidate.portId, nextCandidate.portId) : void 0
|
|
2853
|
+
};
|
|
2854
|
+
});
|
|
2855
|
+
};
|
|
2856
|
+
var getSharedRegionId = (portMap, firstPortId, secondPortId) => {
|
|
2857
|
+
const firstPort = portMap.get(firstPortId);
|
|
2858
|
+
const secondPort = portMap.get(secondPortId);
|
|
2859
|
+
if (!firstPort || !secondPort) return void 0;
|
|
2860
|
+
const firstRegionIds = [firstPort.region1Id, firstPort.region2Id];
|
|
2861
|
+
return firstRegionIds.find(
|
|
2862
|
+
(regionId) => regionId === secondPort.region1Id || regionId === secondPort.region2Id
|
|
2863
|
+
);
|
|
2864
|
+
};
|
|
2865
|
+
|
|
2866
|
+
// lib/pruneDeadEndPorts.ts
|
|
2867
|
+
var pruneDeadEndPorts = (graph, retainedPortIds = []) => {
|
|
2868
|
+
const retainedPortIdSet = new Set(retainedPortIds);
|
|
2869
|
+
const regionPortCounts = new Map(
|
|
2870
|
+
graph.regions.map((region) => [region.regionId, region.ports.length])
|
|
2871
|
+
);
|
|
2872
|
+
const nextPorts = [];
|
|
2873
|
+
for (const region of graph.regions) {
|
|
2874
|
+
region.ports = [];
|
|
2875
|
+
}
|
|
2876
|
+
for (const port of graph.ports) {
|
|
2877
|
+
const isDeadEndPort = regionPortCounts.get(port.region1.regionId) === 1 || regionPortCounts.get(port.region2.regionId) === 1;
|
|
2878
|
+
if (isDeadEndPort && !retainedPortIdSet.has(port.portId)) {
|
|
2879
|
+
continue;
|
|
2880
|
+
}
|
|
2881
|
+
nextPorts.push(port);
|
|
2882
|
+
port.region1.ports.push(port);
|
|
2883
|
+
port.region2.ports.push(port);
|
|
2884
|
+
}
|
|
2885
|
+
graph.ports = nextPorts;
|
|
2886
|
+
graph.regions = graph.regions.filter((region) => region.ports.length > 0);
|
|
2887
|
+
return graph;
|
|
2888
|
+
};
|
|
2889
|
+
|
|
2578
2890
|
// lib/HyperGraphSectionOptimizer/HyperGraphSectionOptimizer.ts
|
|
2579
2891
|
import { BaseSolver as BaseSolver2 } from "@tscircuit/solver-utils";
|
|
2580
2892
|
|
|
@@ -3380,6 +3692,318 @@ var HyperGraphSectionOptimizer = class extends BaseSolver2 {
|
|
|
3380
3692
|
}
|
|
3381
3693
|
};
|
|
3382
3694
|
|
|
3695
|
+
// lib/HyperGraphSectionOptimizer/HyperGraphSectionOptimizer2.ts
|
|
3696
|
+
import { BaseSolver as BaseSolver3 } from "@tscircuit/solver-utils";
|
|
3697
|
+
var HyperGraphSectionOptimizer2 = class extends BaseSolver3 {
|
|
3698
|
+
config;
|
|
3699
|
+
rootSolver;
|
|
3700
|
+
graph;
|
|
3701
|
+
connections;
|
|
3702
|
+
solvedRoutes;
|
|
3703
|
+
activeAttempt = null;
|
|
3704
|
+
targetRegionAttemptCounts = /* @__PURE__ */ new Map();
|
|
3705
|
+
attemptedSectionCount = 0;
|
|
3706
|
+
constructor(input) {
|
|
3707
|
+
super();
|
|
3708
|
+
this.config = normalizeInput(input);
|
|
3709
|
+
this.rootSolver = this.createHyperGraphSolver({
|
|
3710
|
+
inputGraph: this.config.inputGraph,
|
|
3711
|
+
inputConnections: this.config.inputConnections,
|
|
3712
|
+
inputSolvedRoutes: this.config.inputSolvedRoutes
|
|
3713
|
+
});
|
|
3714
|
+
this.graph = this.rootSolver.graph;
|
|
3715
|
+
this.connections = this.rootSolver.connections;
|
|
3716
|
+
this.solvedRoutes = this.rootSolver.solvedRoutes;
|
|
3717
|
+
this.MAX_ITERATIONS = Math.ceil(this.MAX_ITERATIONS * this.config.effort);
|
|
3718
|
+
}
|
|
3719
|
+
getSolverName() {
|
|
3720
|
+
return "HyperGraphSectionOptimizer2";
|
|
3721
|
+
}
|
|
3722
|
+
getConstructorParams() {
|
|
3723
|
+
return {
|
|
3724
|
+
inputGraph: convertHyperGraphToSerializedHyperGraph(this.graph),
|
|
3725
|
+
inputConnections: convertConnectionsToSerializedConnections(
|
|
3726
|
+
this.connections
|
|
3727
|
+
),
|
|
3728
|
+
inputSolvedRoutes: convertSolvedRoutesToSerializedSolvedRoutes(
|
|
3729
|
+
this.solvedRoutes
|
|
3730
|
+
),
|
|
3731
|
+
sectionExpansionHops: this.config.sectionExpansionHops,
|
|
3732
|
+
maxTargetRegionAttempts: this.config.maxTargetRegionAttempts,
|
|
3733
|
+
maxSectionAttempts: this.config.maxSectionAttempts,
|
|
3734
|
+
minCentralRegionCost: this.config.minCentralRegionCost,
|
|
3735
|
+
effort: this.config.effort
|
|
3736
|
+
};
|
|
3737
|
+
}
|
|
3738
|
+
getOutput() {
|
|
3739
|
+
return this.solvedRoutes;
|
|
3740
|
+
}
|
|
3741
|
+
_setup() {
|
|
3742
|
+
this.startNextSectionAttempt();
|
|
3743
|
+
}
|
|
3744
|
+
visualize() {
|
|
3745
|
+
if (this.activeSubSolver) {
|
|
3746
|
+
return this.activeSubSolver.visualize();
|
|
3747
|
+
}
|
|
3748
|
+
return {
|
|
3749
|
+
title: "HyperGraphSectionOptimizer2",
|
|
3750
|
+
points: [],
|
|
3751
|
+
lines: [],
|
|
3752
|
+
rects: [],
|
|
3753
|
+
circles: [],
|
|
3754
|
+
texts: [],
|
|
3755
|
+
polygons: [],
|
|
3756
|
+
arrows: []
|
|
3757
|
+
};
|
|
3758
|
+
}
|
|
3759
|
+
createHyperGraphSolver(input) {
|
|
3760
|
+
const graph = convertSerializedHyperGraphToHyperGraph(input.inputGraph);
|
|
3761
|
+
return new HyperGraphSolver({
|
|
3762
|
+
inputGraph: graph,
|
|
3763
|
+
inputConnections: input.inputConnections,
|
|
3764
|
+
inputSolvedRoutes: convertSerializedSolvedRoutesToSolvedRoutes(
|
|
3765
|
+
input.inputSolvedRoutes,
|
|
3766
|
+
graph
|
|
3767
|
+
)
|
|
3768
|
+
});
|
|
3769
|
+
}
|
|
3770
|
+
getCostOfCentralRegion(region) {
|
|
3771
|
+
const attempts = this.targetRegionAttemptCounts.get(region.regionId) ?? 0;
|
|
3772
|
+
return this.getRegionSolutionCost(this.rootSolver, region) + attempts * 1e4;
|
|
3773
|
+
}
|
|
3774
|
+
getSectionCost(input) {
|
|
3775
|
+
const sectionSolver = this.createHyperGraphSolver({
|
|
3776
|
+
inputGraph: input.solvedGraph,
|
|
3777
|
+
inputConnections: input.solvedGraph.connections ?? [],
|
|
3778
|
+
inputSolvedRoutes: input.solvedGraph.solvedRoutes ?? []
|
|
3779
|
+
});
|
|
3780
|
+
let totalCost = 0;
|
|
3781
|
+
for (const region of sectionSolver.graph.regions) {
|
|
3782
|
+
if (!input.sectionRegionIds.has(region.regionId)) continue;
|
|
3783
|
+
totalCost += this.getRegionSolutionCost(sectionSolver, region);
|
|
3784
|
+
}
|
|
3785
|
+
return totalCost;
|
|
3786
|
+
}
|
|
3787
|
+
_step() {
|
|
3788
|
+
if (!this.activeSubSolver) {
|
|
3789
|
+
this.startNextSectionAttempt();
|
|
3790
|
+
return;
|
|
3791
|
+
}
|
|
3792
|
+
this.activeSubSolver.step();
|
|
3793
|
+
if (!this.activeAttempt) return;
|
|
3794
|
+
if (this.activeSubSolver.failed) {
|
|
3795
|
+
this.rejectActiveAttempt();
|
|
3796
|
+
return;
|
|
3797
|
+
}
|
|
3798
|
+
if (!this.activeSubSolver.solved) return;
|
|
3799
|
+
const solvedBlankSection = {
|
|
3800
|
+
...this.activeAttempt.blankSectionProblem,
|
|
3801
|
+
solvedRoutes: convertSolvedRoutesToSerializedSolvedRoutes(
|
|
3802
|
+
this.activeSubSolver.solvedRoutes
|
|
3803
|
+
)
|
|
3804
|
+
};
|
|
3805
|
+
const mergedGraph = reattachSectionToGraph({
|
|
3806
|
+
fullGraph: this.activeAttempt.fullGraphSnapshot,
|
|
3807
|
+
solvedSectionGraph: solvedBlankSection
|
|
3808
|
+
});
|
|
3809
|
+
const mergedSectionCost = this.getSectionCost({
|
|
3810
|
+
solvedGraph: mergedGraph,
|
|
3811
|
+
sectionRegionIds: this.activeAttempt.sectionRegionIds
|
|
3812
|
+
});
|
|
3813
|
+
if (mergedSectionCost < this.activeAttempt.currentSectionCost) {
|
|
3814
|
+
this.acceptMergedGraph(mergedGraph);
|
|
3815
|
+
return;
|
|
3816
|
+
}
|
|
3817
|
+
this.rejectActiveAttempt();
|
|
3818
|
+
}
|
|
3819
|
+
startNextSectionAttempt() {
|
|
3820
|
+
if (this.attemptedSectionCount >= this.config.maxSectionAttempts) {
|
|
3821
|
+
this.solved = true;
|
|
3822
|
+
return;
|
|
3823
|
+
}
|
|
3824
|
+
const targetRegion = this.selectTargetRegion();
|
|
3825
|
+
if (!targetRegion) {
|
|
3826
|
+
this.solved = true;
|
|
3827
|
+
return;
|
|
3828
|
+
}
|
|
3829
|
+
this.attemptedSectionCount += 1;
|
|
3830
|
+
const nextAttempt = this.createSectionSolveAttempt(targetRegion);
|
|
3831
|
+
if (!nextAttempt) {
|
|
3832
|
+
this.bumpTargetRegionAttemptCount(targetRegion.regionId);
|
|
3833
|
+
return;
|
|
3834
|
+
}
|
|
3835
|
+
this.activeAttempt = nextAttempt;
|
|
3836
|
+
this.activeSubSolver = this.createHyperGraphSolver({
|
|
3837
|
+
inputGraph: nextAttempt.blankSectionProblem,
|
|
3838
|
+
inputConnections: nextAttempt.blankSectionProblem.connections ?? [],
|
|
3839
|
+
inputSolvedRoutes: []
|
|
3840
|
+
});
|
|
3841
|
+
}
|
|
3842
|
+
selectTargetRegion() {
|
|
3843
|
+
let bestRegion = null;
|
|
3844
|
+
let bestCost = Infinity;
|
|
3845
|
+
for (const region of this.graph.regions) {
|
|
3846
|
+
if ((region.assignments?.length ?? 0) === 0) continue;
|
|
3847
|
+
if ((this.targetRegionAttemptCounts.get(region.regionId) ?? 0) >= this.config.maxTargetRegionAttempts) {
|
|
3848
|
+
continue;
|
|
3849
|
+
}
|
|
3850
|
+
const cost = this.getCostOfCentralRegion(region);
|
|
3851
|
+
if (cost <= this.config.minCentralRegionCost) continue;
|
|
3852
|
+
if (cost >= bestCost) continue;
|
|
3853
|
+
bestCost = cost;
|
|
3854
|
+
bestRegion = region;
|
|
3855
|
+
}
|
|
3856
|
+
return bestRegion;
|
|
3857
|
+
}
|
|
3858
|
+
createSectionSolveAttempt(targetRegion) {
|
|
3859
|
+
const fullGraphSnapshot = this.serializeSolvedGraph();
|
|
3860
|
+
const extractedSection = extractSectionOfHyperGraph({
|
|
3861
|
+
graph: fullGraphSnapshot,
|
|
3862
|
+
centralRegionId: targetRegion.regionId,
|
|
3863
|
+
expansionHopsFromCentralRegion: this.config.sectionExpansionHops
|
|
3864
|
+
});
|
|
3865
|
+
const prunedSection = this.pruneSectionForBlanking(extractedSection);
|
|
3866
|
+
if ((prunedSection.connections?.length ?? 0) === 0) {
|
|
3867
|
+
return null;
|
|
3868
|
+
}
|
|
3869
|
+
const sectionRegionIds = this.getSectionRegionIds(extractedSection);
|
|
3870
|
+
return {
|
|
3871
|
+
targetRegionId: targetRegion.regionId,
|
|
3872
|
+
sectionRegionIds,
|
|
3873
|
+
fullGraphSnapshot,
|
|
3874
|
+
blankSectionProblem: createBlankHyperGraph(prunedSection),
|
|
3875
|
+
currentSectionCost: this.getSectionCost({
|
|
3876
|
+
solvedGraph: fullGraphSnapshot,
|
|
3877
|
+
sectionRegionIds
|
|
3878
|
+
})
|
|
3879
|
+
};
|
|
3880
|
+
}
|
|
3881
|
+
acceptMergedGraph(mergedGraph) {
|
|
3882
|
+
this.rootSolver.solvedRoutes = commitSolvedRoutes({
|
|
3883
|
+
graph: this.rootSolver.graph,
|
|
3884
|
+
connections: this.rootSolver.connections,
|
|
3885
|
+
solvedRoutes: this.deserializeSolvedRoutes(mergedGraph)
|
|
3886
|
+
});
|
|
3887
|
+
this.solvedRoutes = this.rootSolver.solvedRoutes;
|
|
3888
|
+
this.graph = this.rootSolver.graph;
|
|
3889
|
+
this.connections = this.rootSolver.connections;
|
|
3890
|
+
for (const regionId of this.activeAttempt?.sectionRegionIds ?? []) {
|
|
3891
|
+
this.targetRegionAttemptCounts.set(regionId, 0);
|
|
3892
|
+
}
|
|
3893
|
+
this.clearActiveAttempt();
|
|
3894
|
+
}
|
|
3895
|
+
rejectActiveAttempt() {
|
|
3896
|
+
if (this.activeSubSolver?.failed) {
|
|
3897
|
+
this.failedSubSolvers ??= [];
|
|
3898
|
+
this.failedSubSolvers.push(this.activeSubSolver);
|
|
3899
|
+
}
|
|
3900
|
+
if (this.activeAttempt) {
|
|
3901
|
+
this.bumpTargetRegionAttemptCount(this.activeAttempt.targetRegionId);
|
|
3902
|
+
}
|
|
3903
|
+
this.clearActiveAttempt();
|
|
3904
|
+
}
|
|
3905
|
+
clearActiveAttempt() {
|
|
3906
|
+
this.activeSubSolver = null;
|
|
3907
|
+
this.activeAttempt = null;
|
|
3908
|
+
}
|
|
3909
|
+
bumpTargetRegionAttemptCount(regionId) {
|
|
3910
|
+
this.targetRegionAttemptCounts.set(
|
|
3911
|
+
regionId,
|
|
3912
|
+
(this.targetRegionAttemptCounts.get(regionId) ?? 0) + 1
|
|
3913
|
+
);
|
|
3914
|
+
}
|
|
3915
|
+
serializeSolvedGraph() {
|
|
3916
|
+
return {
|
|
3917
|
+
...convertHyperGraphToSerializedHyperGraph(this.graph),
|
|
3918
|
+
connections: convertConnectionsToSerializedConnections(this.connections),
|
|
3919
|
+
solvedRoutes: convertSolvedRoutesToSerializedSolvedRoutes(
|
|
3920
|
+
this.solvedRoutes
|
|
3921
|
+
)
|
|
3922
|
+
};
|
|
3923
|
+
}
|
|
3924
|
+
deserializeSolvedRoutes(graph) {
|
|
3925
|
+
if (!graph.solvedRoutes) return [];
|
|
3926
|
+
return convertSerializedSolvedRoutesToSolvedRoutes(
|
|
3927
|
+
graph.solvedRoutes,
|
|
3928
|
+
convertSerializedHyperGraphToHyperGraph(graph)
|
|
3929
|
+
);
|
|
3930
|
+
}
|
|
3931
|
+
getSectionRegionIds(sectionGraph) {
|
|
3932
|
+
const fullRegionIds = new Set(
|
|
3933
|
+
this.graph.regions.map((region) => region.regionId)
|
|
3934
|
+
);
|
|
3935
|
+
return new Set(
|
|
3936
|
+
sectionGraph.regions.map((region) => region.regionId).filter((regionId) => fullRegionIds.has(regionId))
|
|
3937
|
+
);
|
|
3938
|
+
}
|
|
3939
|
+
pruneSectionForBlanking(extractedSection) {
|
|
3940
|
+
const mutableSectionGraph = convertSerializedHyperGraphToHyperGraph(extractedSection);
|
|
3941
|
+
const retainedPortIds = extractedSection.solvedRoutes?.flatMap((solvedRoute) => {
|
|
3942
|
+
const firstPortId = solvedRoute.path[0]?.portId;
|
|
3943
|
+
const lastPortId = solvedRoute.path[solvedRoute.path.length - 1]?.portId;
|
|
3944
|
+
return [firstPortId, lastPortId].filter(
|
|
3945
|
+
(portId) => Boolean(portId)
|
|
3946
|
+
);
|
|
3947
|
+
}) ?? [];
|
|
3948
|
+
pruneDeadEndPorts(mutableSectionGraph, retainedPortIds);
|
|
3949
|
+
return {
|
|
3950
|
+
...convertHyperGraphToSerializedHyperGraph(mutableSectionGraph),
|
|
3951
|
+
connections: extractedSection.connections ? structuredClone(extractedSection.connections) : void 0,
|
|
3952
|
+
solvedRoutes: extractedSection.solvedRoutes ? structuredClone(extractedSection.solvedRoutes) : void 0,
|
|
3953
|
+
_sectionCentralRegionId: extractedSection._sectionCentralRegionId,
|
|
3954
|
+
_sectionRouteBindings: extractedSection._sectionRouteBindings ? structuredClone(extractedSection._sectionRouteBindings) : void 0
|
|
3955
|
+
};
|
|
3956
|
+
}
|
|
3957
|
+
getRegionSolutionCost(solver, region) {
|
|
3958
|
+
const previousConnection = solver.currentConnection;
|
|
3959
|
+
let totalCost = 0;
|
|
3960
|
+
for (const assignment of region.assignments ?? []) {
|
|
3961
|
+
solver.currentConnection = assignment.connection;
|
|
3962
|
+
totalCost += solver.computeIncreasedRegionCostIfPortsAreUsed(
|
|
3963
|
+
region,
|
|
3964
|
+
assignment.regionPort1,
|
|
3965
|
+
assignment.regionPort2
|
|
3966
|
+
);
|
|
3967
|
+
}
|
|
3968
|
+
solver.currentConnection = previousConnection;
|
|
3969
|
+
return totalCost;
|
|
3970
|
+
}
|
|
3971
|
+
};
|
|
3972
|
+
var normalizeInput = (input) => {
|
|
3973
|
+
const inputConnections = input.inputConnections ?? input.inputGraph.connections;
|
|
3974
|
+
const inputSolvedRoutes = input.inputSolvedRoutes ?? input.inputGraph.solvedRoutes;
|
|
3975
|
+
const sectionExpansionHops = input.sectionExpansionHops ?? input.expansionHopsFromCentralRegion;
|
|
3976
|
+
const maxTargetRegionAttempts = input.maxTargetRegionAttempts ?? input.MAX_ATTEMPTS_PER_REGION;
|
|
3977
|
+
if (!inputConnections) {
|
|
3978
|
+
throw new Error("HyperGraphSectionOptimizer2 requires inputConnections");
|
|
3979
|
+
}
|
|
3980
|
+
if (!inputSolvedRoutes) {
|
|
3981
|
+
throw new Error("HyperGraphSectionOptimizer2 requires inputSolvedRoutes");
|
|
3982
|
+
}
|
|
3983
|
+
if (sectionExpansionHops === void 0) {
|
|
3984
|
+
throw new Error("HyperGraphSectionOptimizer2 requires sectionExpansionHops");
|
|
3985
|
+
}
|
|
3986
|
+
if (maxTargetRegionAttempts === void 0) {
|
|
3987
|
+
throw new Error(
|
|
3988
|
+
"HyperGraphSectionOptimizer2 requires maxTargetRegionAttempts"
|
|
3989
|
+
);
|
|
3990
|
+
}
|
|
3991
|
+
return {
|
|
3992
|
+
inputGraph: {
|
|
3993
|
+
...input.inputGraph,
|
|
3994
|
+
connections: void 0,
|
|
3995
|
+
solvedRoutes: void 0
|
|
3996
|
+
},
|
|
3997
|
+
inputConnections: structuredClone(inputConnections),
|
|
3998
|
+
inputSolvedRoutes: structuredClone(inputSolvedRoutes),
|
|
3999
|
+
sectionExpansionHops,
|
|
4000
|
+
maxTargetRegionAttempts,
|
|
4001
|
+
maxSectionAttempts: input.maxSectionAttempts ?? input.MAX_ATTEMPTS_PER_SECTION ?? 500,
|
|
4002
|
+
minCentralRegionCost: input.minCentralRegionCost ?? input.ACCEPTABLE_CENTRAL_REGION_COST ?? 0,
|
|
4003
|
+
effort: input.effort ?? 1
|
|
4004
|
+
};
|
|
4005
|
+
};
|
|
4006
|
+
|
|
3383
4007
|
// node_modules/transformation-matrix/src/applyToPoint.js
|
|
3384
4008
|
function applyToPoint(matrix2, point2) {
|
|
3385
4009
|
return Array.isArray(point2) ? [
|
|
@@ -15305,7 +15929,7 @@ function setStepOfAllObjects(graphics, step) {
|
|
|
15305
15929
|
}
|
|
15306
15930
|
return graphics;
|
|
15307
15931
|
}
|
|
15308
|
-
var
|
|
15932
|
+
var BaseSolver4 = class {
|
|
15309
15933
|
MAX_ITERATIONS = 1e5;
|
|
15310
15934
|
solved = false;
|
|
15311
15935
|
failed = false;
|
|
@@ -15412,7 +16036,7 @@ function definePipelineStep(solverName, solverClass, getConstructorParams, opts
|
|
|
15412
16036
|
onSolved: opts.onSolved
|
|
15413
16037
|
};
|
|
15414
16038
|
}
|
|
15415
|
-
var BasePipelineSolver = class extends
|
|
16039
|
+
var BasePipelineSolver = class extends BaseSolver4 {
|
|
15416
16040
|
startTimeOfStage = {};
|
|
15417
16041
|
endTimeOfStage = {};
|
|
15418
16042
|
timeSpentOnStage = {};
|
|
@@ -15627,7 +16251,7 @@ var clampPointToBounds = (point4, bounds) => ({
|
|
|
15627
16251
|
x: Math.min(bounds.maxX, Math.max(bounds.minX, point4.x)),
|
|
15628
16252
|
y: Math.min(bounds.maxY, Math.max(bounds.minY, point4.y))
|
|
15629
16253
|
});
|
|
15630
|
-
var BuildRegionsSolver = class extends
|
|
16254
|
+
var BuildRegionsSolver = class extends BaseSolver4 {
|
|
15631
16255
|
input;
|
|
15632
16256
|
output = null;
|
|
15633
16257
|
constructor(input) {
|
|
@@ -16048,7 +16672,7 @@ var generateBoundaryPointsWithEdges = (params) => {
|
|
|
16048
16672
|
hadCrossings: resolved.hadCrossings
|
|
16049
16673
|
};
|
|
16050
16674
|
};
|
|
16051
|
-
var GeneratePointsSolver = class extends
|
|
16675
|
+
var GeneratePointsSolver = class extends BaseSolver4 {
|
|
16052
16676
|
input;
|
|
16053
16677
|
output = null;
|
|
16054
16678
|
constructor(input) {
|
|
@@ -16503,7 +17127,7 @@ var mergeCellsPolyanya = (params) => {
|
|
|
16503
17127
|
const depths = liveCells.map(() => 0);
|
|
16504
17128
|
return { cells: liveCells, depths };
|
|
16505
17129
|
};
|
|
16506
|
-
var MergeCellsSolver = class extends
|
|
17130
|
+
var MergeCellsSolver = class extends BaseSolver4 {
|
|
16507
17131
|
input;
|
|
16508
17132
|
output = null;
|
|
16509
17133
|
constructor(input) {
|
|
@@ -16761,7 +17385,7 @@ var filterTris = (params) => {
|
|
|
16761
17385
|
return true;
|
|
16762
17386
|
});
|
|
16763
17387
|
};
|
|
16764
|
-
var TriangulateSolver = class extends
|
|
17388
|
+
var TriangulateSolver = class extends BaseSolver4 {
|
|
16765
17389
|
input;
|
|
16766
17390
|
output = null;
|
|
16767
17391
|
constructor(input) {
|
|
@@ -24719,6 +25343,7 @@ function createConvexViaGraphFromXYConnections(xyConnections, viaTileOrProblem,
|
|
|
24719
25343
|
export {
|
|
24720
25344
|
ConnectBuilder,
|
|
24721
25345
|
HyperGraphSectionOptimizer,
|
|
25346
|
+
HyperGraphSectionOptimizer2,
|
|
24722
25347
|
HyperGraphSolver,
|
|
24723
25348
|
JUMPER_GRAPH_SOLVER_DEFAULTS,
|
|
24724
25349
|
JumperGraphSolver,
|
|
@@ -24732,6 +25357,7 @@ export {
|
|
|
24732
25357
|
calculateGraphBounds,
|
|
24733
25358
|
convertConnectionsToSerializedConnections,
|
|
24734
25359
|
convertHyperGraphToSerializedHyperGraph,
|
|
25360
|
+
createBlankHyperGraph,
|
|
24735
25361
|
createConvexViaGraphFromXYConnections,
|
|
24736
25362
|
createGraphWithConnectionsFromBaseGraph,
|
|
24737
25363
|
createViaGraphWithConnections,
|
|
@@ -24741,6 +25367,8 @@ export {
|
|
|
24741
25367
|
generateJumperGrid,
|
|
24742
25368
|
generateJumperX4Grid,
|
|
24743
25369
|
generateViaTopologyRegions,
|
|
25370
|
+
pruneDeadEndPorts,
|
|
25371
|
+
reattachSectionToGraph,
|
|
24744
25372
|
recommendViaTileFromGraphInput,
|
|
24745
25373
|
rotateGraph90Degrees,
|
|
24746
25374
|
via_tile_4_regions_default as viaTile
|