@tscircuit/hypergraph 0.0.65 → 0.0.67
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 +27 -1
- package/dist/index.js +624 -484
- package/package.json +2 -1
package/dist/index.d.ts
CHANGED
|
@@ -84,6 +84,25 @@ type SerializedHyperGraph = {
|
|
|
84
84
|
ports: SerializedGraphPort[];
|
|
85
85
|
regions: SerializedGraphRegion[];
|
|
86
86
|
};
|
|
87
|
+
type SerializedCandidate = {
|
|
88
|
+
portId: PortId;
|
|
89
|
+
g: number;
|
|
90
|
+
h: number;
|
|
91
|
+
f: number;
|
|
92
|
+
hops: number;
|
|
93
|
+
ripRequired: boolean;
|
|
94
|
+
lastPortId?: PortId;
|
|
95
|
+
lastRegionId?: RegionId;
|
|
96
|
+
nextRegionId?: RegionId;
|
|
97
|
+
};
|
|
98
|
+
type SerializedSolvedRoute = {
|
|
99
|
+
path: SerializedCandidate[];
|
|
100
|
+
connection: SerializedConnection;
|
|
101
|
+
requiredRip: boolean;
|
|
102
|
+
};
|
|
103
|
+
type SerializedHyperGraphWithSolvedRoutes = SerializedHyperGraph & {
|
|
104
|
+
solvedRoutes: SerializedSolvedRoute[];
|
|
105
|
+
};
|
|
87
106
|
type Connection = {
|
|
88
107
|
connectionId: ConnectionId;
|
|
89
108
|
mutuallyConnectedNetworkId: NetworkId;
|
|
@@ -94,12 +113,19 @@ type SerializedConnection = {
|
|
|
94
113
|
connectionId: ConnectionId;
|
|
95
114
|
startRegionId: RegionId;
|
|
96
115
|
endRegionId: RegionId;
|
|
116
|
+
mutuallyConnectedNetworkId?: NetworkId;
|
|
97
117
|
};
|
|
98
118
|
|
|
99
119
|
declare const convertConnectionsToSerializedConnections: (connections: Connection[]) => SerializedConnection[];
|
|
100
120
|
|
|
101
121
|
declare const convertHyperGraphToSerializedHyperGraph: (graph: HyperGraph) => SerializedHyperGraph;
|
|
102
122
|
|
|
123
|
+
declare const extractSectionOfHyperGraph: (input: {
|
|
124
|
+
graph: SerializedHyperGraphWithSolvedRoutes;
|
|
125
|
+
centralRegionId: RegionId;
|
|
126
|
+
expansionHopsFromCentralRegion: number;
|
|
127
|
+
}) => SerializedHyperGraphWithSolvedRoutes;
|
|
128
|
+
|
|
103
129
|
type Node = {
|
|
104
130
|
f: number;
|
|
105
131
|
[key: string]: any;
|
|
@@ -1286,4 +1312,4 @@ declare function generateConvexViaTopologyRegions(opts: {
|
|
|
1286
1312
|
};
|
|
1287
1313
|
};
|
|
1288
1314
|
|
|
1289
|
-
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 SerializedConnection, type SerializedGraphPort, type SerializedGraphRegion, type SerializedHyperGraph, type SerializedRegionPortAssignment, 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, createConvexViaGraphFromXYConnections, createGraphWithConnectionsFromBaseGraph, createViaGraphWithConnections, generateConvexViaTopologyRegions, generateDefaultViaTopologyRegions, generateJumperGrid, generateJumperX4Grid, generateViaTopologyRegions, recommendViaTileFromGraphInput, rotateGraph90Degrees, viaTile4Regions as viaTile };
|
|
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 SerializedHyperGraphWithSolvedRoutes, type SerializedRegionPortAssignment, 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, createConvexViaGraphFromXYConnections, createGraphWithConnectionsFromBaseGraph, createViaGraphWithConnections, extractSectionOfHyperGraph, generateConvexViaTopologyRegions, generateDefaultViaTopologyRegions, generateJumperGrid, generateJumperX4Grid, generateViaTopologyRegions, recommendViaTileFromGraphInput, rotateGraph90Degrees, viaTile4Regions as viaTile };
|
package/dist/index.js
CHANGED
|
@@ -1471,7 +1471,8 @@ var convertConnectionsToSerializedConnections = (connections) => {
|
|
|
1471
1471
|
return connections.map((conn) => ({
|
|
1472
1472
|
connectionId: conn.connectionId,
|
|
1473
1473
|
startRegionId: conn.startRegion.regionId,
|
|
1474
|
-
endRegionId: conn.endRegion.regionId
|
|
1474
|
+
endRegionId: conn.endRegion.regionId,
|
|
1475
|
+
mutuallyConnectedNetworkId: conn.mutuallyConnectedNetworkId
|
|
1475
1476
|
}));
|
|
1476
1477
|
};
|
|
1477
1478
|
|
|
@@ -1496,267 +1497,679 @@ var convertHyperGraphToSerializedHyperGraph = (graph) => {
|
|
|
1496
1497
|
};
|
|
1497
1498
|
};
|
|
1498
1499
|
|
|
1499
|
-
// lib/
|
|
1500
|
-
|
|
1501
|
-
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
|
|
1505
|
-
|
|
1506
|
-
|
|
1507
|
-
|
|
1508
|
-
|
|
1509
|
-
|
|
1510
|
-
|
|
1511
|
-
|
|
1512
|
-
|
|
1513
|
-
|
|
1514
|
-
|
|
1515
|
-
|
|
1516
|
-
|
|
1517
|
-
|
|
1518
|
-
|
|
1519
|
-
|
|
1500
|
+
// lib/HyperGraphSectionOptimizer/getOrCreateBoundaryRegion.ts
|
|
1501
|
+
var getOrCreateBoundaryRegion = ({
|
|
1502
|
+
port,
|
|
1503
|
+
boundaryRegionMap
|
|
1504
|
+
}) => {
|
|
1505
|
+
let boundaryRegion = boundaryRegionMap.get(port.portId);
|
|
1506
|
+
if (!boundaryRegion) {
|
|
1507
|
+
const x = typeof port.d?.x === "number" ? port.d.x : 0;
|
|
1508
|
+
const y = typeof port.d?.y === "number" ? port.d.y : 0;
|
|
1509
|
+
boundaryRegion = {
|
|
1510
|
+
regionId: `__section_boundary__${port.portId}`,
|
|
1511
|
+
ports: [],
|
|
1512
|
+
d: {
|
|
1513
|
+
isBoundaryRegion: true,
|
|
1514
|
+
boundaryPortId: port.portId,
|
|
1515
|
+
...port.d,
|
|
1516
|
+
center: { x, y },
|
|
1517
|
+
bounds: {
|
|
1518
|
+
minX: x - 0.05,
|
|
1519
|
+
maxX: x + 0.05,
|
|
1520
|
+
minY: y - 0.05,
|
|
1521
|
+
maxY: y + 0.05
|
|
1522
|
+
}
|
|
1523
|
+
},
|
|
1524
|
+
assignments: []
|
|
1525
|
+
};
|
|
1526
|
+
boundaryRegionMap.set(port.portId, boundaryRegion);
|
|
1520
1527
|
}
|
|
1521
|
-
return
|
|
1528
|
+
return boundaryRegion;
|
|
1522
1529
|
};
|
|
1523
1530
|
|
|
1524
|
-
// lib/
|
|
1525
|
-
var
|
|
1526
|
-
|
|
1527
|
-
|
|
1528
|
-
|
|
1529
|
-
const
|
|
1530
|
-
|
|
1531
|
-
for (
|
|
1532
|
-
const
|
|
1533
|
-
|
|
1534
|
-
|
|
1535
|
-
|
|
1536
|
-
|
|
1537
|
-
|
|
1531
|
+
// lib/HyperGraphSectionOptimizer/routes/sliceSolvedRouteIntoLocalSection.ts
|
|
1532
|
+
var sliceSolvedRouteIntoLocalSection = (input) => {
|
|
1533
|
+
const { sectionRoute, graph } = input;
|
|
1534
|
+
const localPortIds = new Set(graph.ports.map((port) => port.portId));
|
|
1535
|
+
const originalLocalPath = sectionRoute.globalRoute.path.slice(sectionRoute.sectionStartIndex, sectionRoute.sectionEndIndex + 1).filter((candidate) => localPortIds.has(candidate.port.portId));
|
|
1536
|
+
const path = [];
|
|
1537
|
+
let currentRegion = sectionRoute.sectionConnection.startRegion;
|
|
1538
|
+
for (let index = 0; index < originalLocalPath.length; index++) {
|
|
1539
|
+
const originalCandidate = originalLocalPath[index];
|
|
1540
|
+
const port = graph.ports.find(
|
|
1541
|
+
(candidatePort) => candidatePort.portId === originalCandidate.port.portId
|
|
1542
|
+
);
|
|
1543
|
+
const nextRegion = port.region1 === currentRegion ? port.region2 : port.region1;
|
|
1544
|
+
path.push({
|
|
1545
|
+
port,
|
|
1546
|
+
g: originalCandidate.g,
|
|
1547
|
+
h: originalCandidate.h,
|
|
1548
|
+
f: originalCandidate.f,
|
|
1549
|
+
hops: index,
|
|
1550
|
+
ripRequired: originalCandidate.ripRequired,
|
|
1551
|
+
parent: index > 0 ? path[index - 1] : void 0,
|
|
1552
|
+
lastPort: index > 0 ? path[index - 1].port : void 0,
|
|
1553
|
+
lastRegion: index > 0 ? currentRegion : void 0,
|
|
1554
|
+
nextRegion
|
|
1538
1555
|
});
|
|
1539
|
-
|
|
1540
|
-
for (const port of inputGraph.ports) {
|
|
1541
|
-
const region1 = regionMap.get(port.region1Id ?? port.region1?.regionId);
|
|
1542
|
-
const region2 = regionMap.get(port.region2Id ?? port.region2?.regionId);
|
|
1543
|
-
const hydratedPort = {
|
|
1544
|
-
portId: port.portId,
|
|
1545
|
-
region1,
|
|
1546
|
-
region2,
|
|
1547
|
-
d: port.d
|
|
1548
|
-
};
|
|
1549
|
-
portMap.set(port.portId, hydratedPort);
|
|
1550
|
-
region1.ports.push(hydratedPort);
|
|
1551
|
-
region2.ports.push(hydratedPort);
|
|
1556
|
+
currentRegion = nextRegion;
|
|
1552
1557
|
}
|
|
1553
1558
|
return {
|
|
1554
|
-
|
|
1555
|
-
|
|
1559
|
+
connection: sectionRoute.sectionConnection,
|
|
1560
|
+
path,
|
|
1561
|
+
requiredRip: sectionRoute.globalRoute.requiredRip
|
|
1556
1562
|
};
|
|
1557
1563
|
};
|
|
1558
1564
|
|
|
1559
|
-
// lib/
|
|
1560
|
-
var
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
1564
|
-
|
|
1565
|
-
|
|
1566
|
-
|
|
1567
|
-
|
|
1568
|
-
|
|
1569
|
-
constructor(nodes = [], maxSize = 1e4) {
|
|
1570
|
-
this.maxSize = maxSize;
|
|
1571
|
-
if (nodes.length > 0) {
|
|
1572
|
-
this.heap = [...nodes].sort((a, b) => a.f - b.f).slice(0, this.maxSize);
|
|
1573
|
-
for (let i = Math.floor(this.heap.length / 2) - 1; i >= 0; i--) {
|
|
1574
|
-
this._siftDown(i);
|
|
1575
|
-
}
|
|
1576
|
-
}
|
|
1577
|
-
}
|
|
1578
|
-
/**
|
|
1579
|
-
* Returns the number of elements currently in the queue.
|
|
1580
|
-
*/
|
|
1581
|
-
get size() {
|
|
1582
|
-
return this.heap.length;
|
|
1583
|
-
}
|
|
1584
|
-
/**
|
|
1585
|
-
* Checks if the queue is empty.
|
|
1586
|
-
*/
|
|
1587
|
-
isEmpty() {
|
|
1588
|
-
return this.heap.length === 0;
|
|
1565
|
+
// lib/HyperGraphSectionOptimizer/sections/getRouteSectionSpan.ts
|
|
1566
|
+
var getRouteSectionSpan = (route, sectionRegionIds) => {
|
|
1567
|
+
let startIndex = -1;
|
|
1568
|
+
let endIndex = -1;
|
|
1569
|
+
for (let i = 0; i < route.path.length; i++) {
|
|
1570
|
+
const candidate = route.path[i];
|
|
1571
|
+
const touchesSection = candidate.lastRegion && sectionRegionIds.has(candidate.lastRegion.regionId) || candidate.nextRegion && sectionRegionIds.has(candidate.nextRegion.regionId);
|
|
1572
|
+
if (!touchesSection) continue;
|
|
1573
|
+
if (startIndex === -1) startIndex = i;
|
|
1574
|
+
endIndex = i;
|
|
1589
1575
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
1594
|
-
|
|
1595
|
-
|
|
1596
|
-
|
|
1597
|
-
|
|
1576
|
+
if (startIndex === -1) return null;
|
|
1577
|
+
return { startIndex, endIndex };
|
|
1578
|
+
};
|
|
1579
|
+
|
|
1580
|
+
// lib/HyperGraphSectionOptimizer/sections/getSectionRegionIds.ts
|
|
1581
|
+
var getSectionRegionIds = ({
|
|
1582
|
+
centralRegion,
|
|
1583
|
+
expansionHopsFromCentralRegion
|
|
1584
|
+
}) => {
|
|
1585
|
+
const sectionRegionIds = /* @__PURE__ */ new Set([centralRegion.regionId]);
|
|
1586
|
+
const queue = [
|
|
1587
|
+
{ region: centralRegion, hops: 0 }
|
|
1588
|
+
];
|
|
1589
|
+
while (queue.length > 0) {
|
|
1590
|
+
const { region, hops } = queue.shift();
|
|
1591
|
+
if (hops >= expansionHopsFromCentralRegion + 1) continue;
|
|
1592
|
+
for (const port of region.ports) {
|
|
1593
|
+
const nextRegion = port.region1 === region ? port.region2 : port.region1;
|
|
1594
|
+
if (sectionRegionIds.has(nextRegion.regionId)) continue;
|
|
1595
|
+
sectionRegionIds.add(nextRegion.regionId);
|
|
1596
|
+
queue.push({ region: nextRegion, hops: hops + 1 });
|
|
1598
1597
|
}
|
|
1599
|
-
return this.heap[0] ?? null;
|
|
1600
1598
|
}
|
|
1601
|
-
|
|
1602
|
-
|
|
1603
|
-
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1599
|
+
return sectionRegionIds;
|
|
1600
|
+
};
|
|
1601
|
+
|
|
1602
|
+
// lib/HyperGraphSectionOptimizer/sections/getSectionOfHyperGraphAsHyperGraph.ts
|
|
1603
|
+
var getSectionOfHyperGraphAsHyperGraph = (input) => {
|
|
1604
|
+
const { graph, solvedRoutes, centralRegion, expansionHopsFromCentralRegion } = input;
|
|
1605
|
+
const sectionRegionIds = getSectionRegionIds({
|
|
1606
|
+
graph,
|
|
1607
|
+
centralRegion,
|
|
1608
|
+
expansionHopsFromCentralRegion
|
|
1609
|
+
});
|
|
1610
|
+
const clonedRegionMap = /* @__PURE__ */ new Map();
|
|
1611
|
+
const boundaryRegionMap = /* @__PURE__ */ new Map();
|
|
1612
|
+
const clonedPorts = [];
|
|
1613
|
+
for (const region of graph.regions) {
|
|
1614
|
+
if (!sectionRegionIds.has(region.regionId)) continue;
|
|
1615
|
+
clonedRegionMap.set(region.regionId, {
|
|
1616
|
+
regionId: region.regionId,
|
|
1617
|
+
ports: [],
|
|
1618
|
+
d: region.d ? structuredClone(region.d) : region.d,
|
|
1619
|
+
assignments: []
|
|
1620
|
+
});
|
|
1609
1621
|
}
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
if (lastNode !== void 0) {
|
|
1626
|
-
this.heap[0] = lastNode;
|
|
1627
|
-
this._siftDown(0);
|
|
1622
|
+
for (const port of graph.ports) {
|
|
1623
|
+
const region1InSection = sectionRegionIds.has(port.region1.regionId);
|
|
1624
|
+
const region2InSection = sectionRegionIds.has(port.region2.regionId);
|
|
1625
|
+
if (!region1InSection && !region2InSection) continue;
|
|
1626
|
+
if (region1InSection && region2InSection) {
|
|
1627
|
+
const clonedPort2 = {
|
|
1628
|
+
portId: port.portId,
|
|
1629
|
+
region1: clonedRegionMap.get(port.region1.regionId),
|
|
1630
|
+
region2: clonedRegionMap.get(port.region2.regionId),
|
|
1631
|
+
d: port.d
|
|
1632
|
+
};
|
|
1633
|
+
clonedPort2.region1.ports.push(clonedPort2);
|
|
1634
|
+
clonedPort2.region2.ports.push(clonedPort2);
|
|
1635
|
+
clonedPorts.push(clonedPort2);
|
|
1636
|
+
continue;
|
|
1628
1637
|
}
|
|
1629
|
-
|
|
1638
|
+
const insideRegion = region1InSection ? port.region1 : port.region2;
|
|
1639
|
+
const boundaryRegion = getOrCreateBoundaryRegion({
|
|
1640
|
+
port,
|
|
1641
|
+
boundaryRegionMap
|
|
1642
|
+
});
|
|
1643
|
+
const clonedPort = {
|
|
1644
|
+
portId: port.portId,
|
|
1645
|
+
region1: clonedRegionMap.get(insideRegion.regionId),
|
|
1646
|
+
region2: boundaryRegion,
|
|
1647
|
+
d: port.d
|
|
1648
|
+
};
|
|
1649
|
+
clonedPort.region1.ports.push(clonedPort);
|
|
1650
|
+
clonedPort.region2.ports.push(clonedPort);
|
|
1651
|
+
clonedPorts.push(clonedPort);
|
|
1630
1652
|
}
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1639
|
-
|
|
1640
|
-
|
|
1641
|
-
|
|
1642
|
-
|
|
1643
|
-
|
|
1644
|
-
|
|
1645
|
-
|
|
1646
|
-
|
|
1647
|
-
|
|
1648
|
-
|
|
1649
|
-
|
|
1650
|
-
|
|
1651
|
-
|
|
1652
|
-
|
|
1653
|
-
|
|
1654
|
-
|
|
1653
|
+
const sectionGraph = {
|
|
1654
|
+
regions: [...clonedRegionMap.values(), ...boundaryRegionMap.values()],
|
|
1655
|
+
ports: clonedPorts
|
|
1656
|
+
};
|
|
1657
|
+
const sectionRoutes = [];
|
|
1658
|
+
const sectionConnections = [];
|
|
1659
|
+
const sectionRegionMap = new Map(
|
|
1660
|
+
sectionGraph.regions.map((region) => [region.regionId, region])
|
|
1661
|
+
);
|
|
1662
|
+
for (const solvedRoute of solvedRoutes) {
|
|
1663
|
+
const span = getRouteSectionSpan(solvedRoute, sectionRegionIds);
|
|
1664
|
+
if (!span) continue;
|
|
1665
|
+
const startCandidate = solvedRoute.path[span.startIndex];
|
|
1666
|
+
const endCandidate = solvedRoute.path[span.endIndex];
|
|
1667
|
+
let startRegionId;
|
|
1668
|
+
let startRegion;
|
|
1669
|
+
if (sectionRegionIds.has(solvedRoute.connection.startRegion.regionId)) {
|
|
1670
|
+
startRegionId = solvedRoute.connection.startRegion.regionId;
|
|
1671
|
+
startRegion = sectionRegionMap.get(startRegionId);
|
|
1672
|
+
} else {
|
|
1673
|
+
const boundaryRegion = getOrCreateBoundaryRegion({
|
|
1674
|
+
port: startCandidate.port,
|
|
1675
|
+
boundaryRegionMap
|
|
1676
|
+
});
|
|
1677
|
+
startRegionId = boundaryRegion.regionId;
|
|
1678
|
+
startRegion = boundaryRegion;
|
|
1679
|
+
if (!sectionRegionMap.has(startRegionId)) {
|
|
1680
|
+
sectionRegionMap.set(startRegionId, boundaryRegion);
|
|
1655
1681
|
}
|
|
1656
|
-
this._swap(currentIndex, parentIndex);
|
|
1657
|
-
currentIndex = parentIndex;
|
|
1658
1682
|
}
|
|
1659
|
-
|
|
1660
|
-
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
if (
|
|
1672
|
-
|
|
1673
|
-
}
|
|
1674
|
-
if (rightChildIndex < heapSize && this.heap[rightChildIndex].f < this.heap[smallestIndex].f) {
|
|
1675
|
-
smallestIndex = rightChildIndex;
|
|
1676
|
-
}
|
|
1677
|
-
if (smallestIndex !== currentIndex) {
|
|
1678
|
-
this._swap(currentIndex, smallestIndex);
|
|
1679
|
-
currentIndex = smallestIndex;
|
|
1680
|
-
} else {
|
|
1681
|
-
break;
|
|
1683
|
+
let endRegionId;
|
|
1684
|
+
let endRegion;
|
|
1685
|
+
if (sectionRegionIds.has(solvedRoute.connection.endRegion.regionId)) {
|
|
1686
|
+
endRegionId = solvedRoute.connection.endRegion.regionId;
|
|
1687
|
+
endRegion = sectionRegionMap.get(endRegionId);
|
|
1688
|
+
} else {
|
|
1689
|
+
const boundaryRegion = getOrCreateBoundaryRegion({
|
|
1690
|
+
port: endCandidate.port,
|
|
1691
|
+
boundaryRegionMap
|
|
1692
|
+
});
|
|
1693
|
+
endRegionId = boundaryRegion.regionId;
|
|
1694
|
+
endRegion = boundaryRegion;
|
|
1695
|
+
if (!sectionRegionMap.has(endRegionId)) {
|
|
1696
|
+
sectionRegionMap.set(endRegionId, boundaryRegion);
|
|
1682
1697
|
}
|
|
1683
1698
|
}
|
|
1699
|
+
if (!startRegion) {
|
|
1700
|
+
console.error(
|
|
1701
|
+
`[getSectionOfHyperGraphAsHyperGraph] CRITICAL ERROR: startRegion not found!`
|
|
1702
|
+
);
|
|
1703
|
+
console.error(` Looking for: ${startRegionId}`);
|
|
1704
|
+
console.error(
|
|
1705
|
+
` Route connection: ${solvedRoute.connection.connectionId}`
|
|
1706
|
+
);
|
|
1707
|
+
console.error(
|
|
1708
|
+
` Original startRegion: ${solvedRoute.connection.startRegion.regionId}`
|
|
1709
|
+
);
|
|
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);
|
|
1684
1764
|
}
|
|
1685
|
-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
1691
|
-
|
|
1692
|
-
|
|
1693
|
-
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
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;
|
|
1697
1778
|
}
|
|
1698
|
-
|
|
1699
|
-
|
|
1700
|
-
|
|
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
|
+
});
|
|
1701
1789
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
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);
|
|
1705
1802
|
}
|
|
1803
|
+
return {
|
|
1804
|
+
ports: Array.from(portMap.values()),
|
|
1805
|
+
regions: Array.from(regionMap.values())
|
|
1806
|
+
};
|
|
1706
1807
|
};
|
|
1707
1808
|
|
|
1708
|
-
// lib/
|
|
1709
|
-
var
|
|
1710
|
-
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
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
|
+
}
|
|
1715
1827
|
}
|
|
1828
|
+
return connections;
|
|
1716
1829
|
};
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
solvedRoutes
|
|
1721
|
-
}) => {
|
|
1830
|
+
|
|
1831
|
+
// lib/convertSerializedSolvedRoutesToSolvedRoutes.ts
|
|
1832
|
+
var convertSerializedSolvedRoutesToSolvedRoutes = (inputSolvedRoutes, graph) => {
|
|
1722
1833
|
const portMap = new Map(graph.ports.map((port) => [port.portId, port]));
|
|
1723
1834
|
const regionMap = new Map(
|
|
1724
1835
|
graph.regions.map((region) => [region.regionId, region])
|
|
1725
1836
|
);
|
|
1726
1837
|
const connectionMap = new Map(
|
|
1727
|
-
|
|
1838
|
+
convertSerializedConnectionsToConnections(
|
|
1839
|
+
inputSolvedRoutes.map((route) => route.connection),
|
|
1840
|
+
graph
|
|
1841
|
+
).map((connection) => [connection.connectionId, connection])
|
|
1728
1842
|
);
|
|
1729
|
-
|
|
1843
|
+
return inputSolvedRoutes.map((inputSolvedRoute) => {
|
|
1730
1844
|
const path = [];
|
|
1731
|
-
for (const originalCandidate of
|
|
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
|
+
}
|
|
1732
1852
|
const candidate = {
|
|
1733
|
-
port
|
|
1853
|
+
port,
|
|
1734
1854
|
g: originalCandidate.g,
|
|
1735
1855
|
h: originalCandidate.h,
|
|
1736
1856
|
f: originalCandidate.f,
|
|
1737
1857
|
hops: originalCandidate.hops,
|
|
1738
1858
|
ripRequired: originalCandidate.ripRequired
|
|
1739
1859
|
};
|
|
1740
|
-
if (originalCandidate.
|
|
1741
|
-
candidate.lastPort =
|
|
1860
|
+
if (originalCandidate.lastPortId) {
|
|
1861
|
+
candidate.lastPort = getRequiredPort(
|
|
1862
|
+
portMap,
|
|
1863
|
+
originalCandidate.lastPortId,
|
|
1864
|
+
inputSolvedRoute.connection.connectionId
|
|
1865
|
+
);
|
|
1742
1866
|
}
|
|
1743
|
-
if (originalCandidate.
|
|
1744
|
-
candidate.lastRegion =
|
|
1745
|
-
|
|
1867
|
+
if (originalCandidate.lastRegionId) {
|
|
1868
|
+
candidate.lastRegion = getRequiredRegion(
|
|
1869
|
+
regionMap,
|
|
1870
|
+
originalCandidate.lastRegionId,
|
|
1871
|
+
inputSolvedRoute.connection.connectionId
|
|
1746
1872
|
);
|
|
1747
1873
|
}
|
|
1748
|
-
if (originalCandidate.
|
|
1749
|
-
candidate.nextRegion =
|
|
1750
|
-
|
|
1874
|
+
if (originalCandidate.nextRegionId) {
|
|
1875
|
+
candidate.nextRegion = getRequiredRegion(
|
|
1876
|
+
regionMap,
|
|
1877
|
+
originalCandidate.nextRegionId,
|
|
1878
|
+
inputSolvedRoute.connection.connectionId
|
|
1751
1879
|
);
|
|
1752
1880
|
}
|
|
1753
1881
|
const parent = path[path.length - 1];
|
|
1754
1882
|
if (parent) candidate.parent = parent;
|
|
1755
1883
|
path.push(candidate);
|
|
1756
1884
|
}
|
|
1885
|
+
const connection = connectionMap.get(
|
|
1886
|
+
inputSolvedRoute.connection.connectionId
|
|
1887
|
+
);
|
|
1888
|
+
if (!connection) {
|
|
1889
|
+
throw new Error(
|
|
1890
|
+
`Connection ${inputSolvedRoute.connection.connectionId} not found while deserializing solved route`
|
|
1891
|
+
);
|
|
1892
|
+
}
|
|
1757
1893
|
return {
|
|
1758
1894
|
path,
|
|
1759
|
-
connection
|
|
1895
|
+
connection,
|
|
1896
|
+
requiredRip: inputSolvedRoute.requiredRip
|
|
1897
|
+
};
|
|
1898
|
+
});
|
|
1899
|
+
};
|
|
1900
|
+
var getRequiredPort = (portMap, portId, connectionId) => {
|
|
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}`
|
|
1914
|
+
);
|
|
1915
|
+
}
|
|
1916
|
+
return region;
|
|
1917
|
+
};
|
|
1918
|
+
|
|
1919
|
+
// lib/convertSolvedRoutesToSerializedSolvedRoutes.ts
|
|
1920
|
+
var convertSolvedRoutesToSerializedSolvedRoutes = (solvedRoutes) => {
|
|
1921
|
+
return solvedRoutes.map((solvedRoute) => ({
|
|
1922
|
+
path: solvedRoute.path.map((candidate) => ({
|
|
1923
|
+
portId: candidate.port.portId,
|
|
1924
|
+
g: candidate.g,
|
|
1925
|
+
h: candidate.h,
|
|
1926
|
+
f: candidate.f,
|
|
1927
|
+
hops: candidate.hops,
|
|
1928
|
+
ripRequired: candidate.ripRequired,
|
|
1929
|
+
lastPortId: candidate.lastPort?.portId,
|
|
1930
|
+
lastRegionId: candidate.lastRegion?.regionId,
|
|
1931
|
+
nextRegionId: candidate.nextRegion?.regionId
|
|
1932
|
+
})),
|
|
1933
|
+
connection: convertConnectionsToSerializedConnections([
|
|
1934
|
+
solvedRoute.connection
|
|
1935
|
+
])[0],
|
|
1936
|
+
requiredRip: solvedRoute.requiredRip
|
|
1937
|
+
}));
|
|
1938
|
+
};
|
|
1939
|
+
|
|
1940
|
+
// lib/extractSectionOfHyperGraph.ts
|
|
1941
|
+
var extractSectionOfHyperGraph = (input) => {
|
|
1942
|
+
const deserializedGraph = convertSerializedHyperGraphToHyperGraph(input.graph);
|
|
1943
|
+
const centralRegion = deserializedGraph.regions.find(
|
|
1944
|
+
(region) => region.regionId === input.centralRegionId
|
|
1945
|
+
);
|
|
1946
|
+
if (!centralRegion) {
|
|
1947
|
+
throw new Error(
|
|
1948
|
+
`Central region ${input.centralRegionId} not found in hypergraph`
|
|
1949
|
+
);
|
|
1950
|
+
}
|
|
1951
|
+
const solvedRoutes = convertSerializedSolvedRoutesToSolvedRoutes(
|
|
1952
|
+
input.graph.solvedRoutes,
|
|
1953
|
+
deserializedGraph
|
|
1954
|
+
);
|
|
1955
|
+
const section = getSectionOfHyperGraphAsHyperGraph({
|
|
1956
|
+
graph: deserializedGraph,
|
|
1957
|
+
solvedRoutes,
|
|
1958
|
+
centralRegion,
|
|
1959
|
+
expansionHopsFromCentralRegion: input.expansionHopsFromCentralRegion
|
|
1960
|
+
});
|
|
1961
|
+
return {
|
|
1962
|
+
...convertHyperGraphToSerializedHyperGraph(section.graph),
|
|
1963
|
+
solvedRoutes: convertSolvedRoutesToSerializedSolvedRoutes(
|
|
1964
|
+
section.sectionRoutes.map((route) => route.sectionRoute)
|
|
1965
|
+
)
|
|
1966
|
+
};
|
|
1967
|
+
};
|
|
1968
|
+
|
|
1969
|
+
// lib/HyperGraphSolver.ts
|
|
1970
|
+
import { BaseSolver } from "@tscircuit/solver-utils";
|
|
1971
|
+
|
|
1972
|
+
// lib/PriorityQueue.ts
|
|
1973
|
+
var PriorityQueue = class {
|
|
1974
|
+
// Store the heap as an array. Index 0 is the root (highest priority/smallest 'f').
|
|
1975
|
+
heap = [];
|
|
1976
|
+
maxSize;
|
|
1977
|
+
/**
|
|
1978
|
+
* Creates a new Priority Queue.
|
|
1979
|
+
* @param nodes An optional initial array of nodes to populate the queue.
|
|
1980
|
+
* @param maxSize The maximum number of elements the queue can hold. Defaults to 10,000.
|
|
1981
|
+
*/
|
|
1982
|
+
constructor(nodes = [], maxSize = 1e4) {
|
|
1983
|
+
this.maxSize = maxSize;
|
|
1984
|
+
if (nodes.length > 0) {
|
|
1985
|
+
this.heap = [...nodes].sort((a, b) => a.f - b.f).slice(0, this.maxSize);
|
|
1986
|
+
for (let i = Math.floor(this.heap.length / 2) - 1; i >= 0; i--) {
|
|
1987
|
+
this._siftDown(i);
|
|
1988
|
+
}
|
|
1989
|
+
}
|
|
1990
|
+
}
|
|
1991
|
+
/**
|
|
1992
|
+
* Returns the number of elements currently in the queue.
|
|
1993
|
+
*/
|
|
1994
|
+
get size() {
|
|
1995
|
+
return this.heap.length;
|
|
1996
|
+
}
|
|
1997
|
+
/**
|
|
1998
|
+
* Checks if the queue is empty.
|
|
1999
|
+
*/
|
|
2000
|
+
isEmpty() {
|
|
2001
|
+
return this.heap.length === 0;
|
|
2002
|
+
}
|
|
2003
|
+
/**
|
|
2004
|
+
* Returns the node with the highest priority (smallest 'f') without removing it.
|
|
2005
|
+
* Returns null if the queue is empty.
|
|
2006
|
+
* @returns The highest priority node or null.
|
|
2007
|
+
*/
|
|
2008
|
+
peek() {
|
|
2009
|
+
if (this.isEmpty()) {
|
|
2010
|
+
return null;
|
|
2011
|
+
}
|
|
2012
|
+
return this.heap[0] ?? null;
|
|
2013
|
+
}
|
|
2014
|
+
/**
|
|
2015
|
+
* Returns up to N nodes with the highest priority (smallest 'f') without removing them.
|
|
2016
|
+
* Nodes are returned sorted by priority (smallest 'f' first).
|
|
2017
|
+
* @param count Maximum number of nodes to return.
|
|
2018
|
+
* @returns Array of nodes sorted by priority.
|
|
2019
|
+
*/
|
|
2020
|
+
peekMany(count) {
|
|
2021
|
+
return [...this.heap].sort((a, b) => a.f - b.f).slice(0, count);
|
|
2022
|
+
}
|
|
2023
|
+
/**
|
|
2024
|
+
* Removes and returns the node with the highest priority (smallest 'f').
|
|
2025
|
+
* Returns null if the queue is empty.
|
|
2026
|
+
* Maintains the heap property.
|
|
2027
|
+
* @returns The highest priority node or null.
|
|
2028
|
+
*/
|
|
2029
|
+
dequeue() {
|
|
2030
|
+
if (this.isEmpty()) {
|
|
2031
|
+
return null;
|
|
2032
|
+
}
|
|
2033
|
+
const minNode = this.heap[0];
|
|
2034
|
+
const lastNode = this.heap.pop();
|
|
2035
|
+
if (this.heap.length === 0 && lastNode !== void 0) {
|
|
2036
|
+
return minNode;
|
|
2037
|
+
}
|
|
2038
|
+
if (lastNode !== void 0) {
|
|
2039
|
+
this.heap[0] = lastNode;
|
|
2040
|
+
this._siftDown(0);
|
|
2041
|
+
}
|
|
2042
|
+
return minNode;
|
|
2043
|
+
}
|
|
2044
|
+
/**
|
|
2045
|
+
* Adds a new node to the queue.
|
|
2046
|
+
* Maintains the heap property.
|
|
2047
|
+
* If the queue is full (at maxSize), the node is not added.
|
|
2048
|
+
* @param node The node to add.
|
|
2049
|
+
*/
|
|
2050
|
+
enqueue(node) {
|
|
2051
|
+
if (this.heap.length >= this.maxSize) {
|
|
2052
|
+
return;
|
|
2053
|
+
}
|
|
2054
|
+
this.heap.push(node);
|
|
2055
|
+
this._siftUp(this.heap.length - 1);
|
|
2056
|
+
}
|
|
2057
|
+
// --- Private Helper Methods ---
|
|
2058
|
+
/**
|
|
2059
|
+
* Moves the node at the given index up the heap to maintain the heap property.
|
|
2060
|
+
* @param index The index of the node to sift up.
|
|
2061
|
+
*/
|
|
2062
|
+
_siftUp(index) {
|
|
2063
|
+
let currentIndex = index;
|
|
2064
|
+
while (currentIndex > 0) {
|
|
2065
|
+
const parentIndex = this._parentIndex(currentIndex);
|
|
2066
|
+
if (this.heap[parentIndex].f <= this.heap[currentIndex].f) {
|
|
2067
|
+
break;
|
|
2068
|
+
}
|
|
2069
|
+
this._swap(currentIndex, parentIndex);
|
|
2070
|
+
currentIndex = parentIndex;
|
|
2071
|
+
}
|
|
2072
|
+
}
|
|
2073
|
+
/**
|
|
2074
|
+
* Moves the node at the given index down the heap to maintain the heap property.
|
|
2075
|
+
* @param index The index of the node to sift down.
|
|
2076
|
+
*/
|
|
2077
|
+
_siftDown(index) {
|
|
2078
|
+
let currentIndex = index;
|
|
2079
|
+
const heapSize = this.heap.length;
|
|
2080
|
+
while (true) {
|
|
2081
|
+
const leftChildIndex = this._leftChildIndex(currentIndex);
|
|
2082
|
+
const rightChildIndex = this._rightChildIndex(currentIndex);
|
|
2083
|
+
let smallestIndex = currentIndex;
|
|
2084
|
+
if (leftChildIndex < heapSize && this.heap[leftChildIndex].f < this.heap[smallestIndex].f) {
|
|
2085
|
+
smallestIndex = leftChildIndex;
|
|
2086
|
+
}
|
|
2087
|
+
if (rightChildIndex < heapSize && this.heap[rightChildIndex].f < this.heap[smallestIndex].f) {
|
|
2088
|
+
smallestIndex = rightChildIndex;
|
|
2089
|
+
}
|
|
2090
|
+
if (smallestIndex !== currentIndex) {
|
|
2091
|
+
this._swap(currentIndex, smallestIndex);
|
|
2092
|
+
currentIndex = smallestIndex;
|
|
2093
|
+
} else {
|
|
2094
|
+
break;
|
|
2095
|
+
}
|
|
2096
|
+
}
|
|
2097
|
+
}
|
|
2098
|
+
/**
|
|
2099
|
+
* Swaps two elements in the heap array.
|
|
2100
|
+
* @param i Index of the first element.
|
|
2101
|
+
* @param j Index of the second element.
|
|
2102
|
+
*/
|
|
2103
|
+
_swap(i, j) {
|
|
2104
|
+
;
|
|
2105
|
+
[this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
|
|
2106
|
+
}
|
|
2107
|
+
/** Calculates the parent index of a node. */
|
|
2108
|
+
_parentIndex(index) {
|
|
2109
|
+
return Math.floor((index - 1) / 2);
|
|
2110
|
+
}
|
|
2111
|
+
/** Calculates the left child index of a node. */
|
|
2112
|
+
_leftChildIndex(index) {
|
|
2113
|
+
return 2 * index + 1;
|
|
2114
|
+
}
|
|
2115
|
+
/** Calculates the right child index of a node. */
|
|
2116
|
+
_rightChildIndex(index) {
|
|
2117
|
+
return 2 * index + 2;
|
|
2118
|
+
}
|
|
2119
|
+
};
|
|
2120
|
+
|
|
2121
|
+
// lib/solvedRoutes.ts
|
|
2122
|
+
var clearAssignmentsFromGraph = (graph) => {
|
|
2123
|
+
for (const region of graph.regions) {
|
|
2124
|
+
region.assignments = [];
|
|
2125
|
+
}
|
|
2126
|
+
for (const port of graph.ports) {
|
|
2127
|
+
port.assignment = void 0;
|
|
2128
|
+
}
|
|
2129
|
+
};
|
|
2130
|
+
var commitSolvedRoutes = ({
|
|
2131
|
+
graph,
|
|
2132
|
+
connections,
|
|
2133
|
+
solvedRoutes
|
|
2134
|
+
}) => {
|
|
2135
|
+
const portMap = new Map(graph.ports.map((port) => [port.portId, port]));
|
|
2136
|
+
const regionMap = new Map(
|
|
2137
|
+
graph.regions.map((region) => [region.regionId, region])
|
|
2138
|
+
);
|
|
2139
|
+
const connectionMap = new Map(
|
|
2140
|
+
connections.map((connection) => [connection.connectionId, connection])
|
|
2141
|
+
);
|
|
2142
|
+
const committedSolvedRoutes = solvedRoutes.map((solvedRoute) => {
|
|
2143
|
+
const path = [];
|
|
2144
|
+
for (const originalCandidate of solvedRoute.path) {
|
|
2145
|
+
const candidate = {
|
|
2146
|
+
port: portMap.get(originalCandidate.port.portId),
|
|
2147
|
+
g: originalCandidate.g,
|
|
2148
|
+
h: originalCandidate.h,
|
|
2149
|
+
f: originalCandidate.f,
|
|
2150
|
+
hops: originalCandidate.hops,
|
|
2151
|
+
ripRequired: originalCandidate.ripRequired
|
|
2152
|
+
};
|
|
2153
|
+
if (originalCandidate.lastPort) {
|
|
2154
|
+
candidate.lastPort = portMap.get(originalCandidate.lastPort.portId);
|
|
2155
|
+
}
|
|
2156
|
+
if (originalCandidate.lastRegion) {
|
|
2157
|
+
candidate.lastRegion = regionMap.get(
|
|
2158
|
+
originalCandidate.lastRegion.regionId
|
|
2159
|
+
);
|
|
2160
|
+
}
|
|
2161
|
+
if (originalCandidate.nextRegion) {
|
|
2162
|
+
candidate.nextRegion = regionMap.get(
|
|
2163
|
+
originalCandidate.nextRegion.regionId
|
|
2164
|
+
);
|
|
2165
|
+
}
|
|
2166
|
+
const parent = path[path.length - 1];
|
|
2167
|
+
if (parent) candidate.parent = parent;
|
|
2168
|
+
path.push(candidate);
|
|
2169
|
+
}
|
|
2170
|
+
return {
|
|
2171
|
+
path,
|
|
2172
|
+
connection: connectionMap.get(solvedRoute.connection.connectionId),
|
|
1760
2173
|
requiredRip: solvedRoute.requiredRip
|
|
1761
2174
|
};
|
|
1762
2175
|
});
|
|
@@ -2640,280 +3053,6 @@ var previewSectionReplacement = (input) => {
|
|
|
2640
3053
|
});
|
|
2641
3054
|
};
|
|
2642
3055
|
|
|
2643
|
-
// lib/HyperGraphSectionOptimizer/getOrCreateBoundaryRegion.ts
|
|
2644
|
-
var getOrCreateBoundaryRegion = ({
|
|
2645
|
-
port,
|
|
2646
|
-
boundaryRegionMap
|
|
2647
|
-
}) => {
|
|
2648
|
-
let boundaryRegion = boundaryRegionMap.get(port.portId);
|
|
2649
|
-
if (!boundaryRegion) {
|
|
2650
|
-
const x = typeof port.d?.x === "number" ? port.d.x : 0;
|
|
2651
|
-
const y = typeof port.d?.y === "number" ? port.d.y : 0;
|
|
2652
|
-
boundaryRegion = {
|
|
2653
|
-
regionId: `__section_boundary__${port.portId}`,
|
|
2654
|
-
ports: [],
|
|
2655
|
-
d: {
|
|
2656
|
-
isBoundaryRegion: true,
|
|
2657
|
-
boundaryPortId: port.portId,
|
|
2658
|
-
...port.d,
|
|
2659
|
-
center: { x, y },
|
|
2660
|
-
bounds: {
|
|
2661
|
-
minX: x - 0.05,
|
|
2662
|
-
maxX: x + 0.05,
|
|
2663
|
-
minY: y - 0.05,
|
|
2664
|
-
maxY: y + 0.05
|
|
2665
|
-
}
|
|
2666
|
-
},
|
|
2667
|
-
assignments: []
|
|
2668
|
-
};
|
|
2669
|
-
boundaryRegionMap.set(port.portId, boundaryRegion);
|
|
2670
|
-
}
|
|
2671
|
-
return boundaryRegion;
|
|
2672
|
-
};
|
|
2673
|
-
|
|
2674
|
-
// lib/HyperGraphSectionOptimizer/routes/sliceSolvedRouteIntoLocalSection.ts
|
|
2675
|
-
var sliceSolvedRouteIntoLocalSection = (input) => {
|
|
2676
|
-
const { sectionRoute, graph } = input;
|
|
2677
|
-
const localPortIds = new Set(graph.ports.map((port) => port.portId));
|
|
2678
|
-
const originalLocalPath = sectionRoute.globalRoute.path.slice(sectionRoute.sectionStartIndex, sectionRoute.sectionEndIndex + 1).filter((candidate) => localPortIds.has(candidate.port.portId));
|
|
2679
|
-
const path = [];
|
|
2680
|
-
let currentRegion = sectionRoute.sectionConnection.startRegion;
|
|
2681
|
-
for (let index = 0; index < originalLocalPath.length; index++) {
|
|
2682
|
-
const originalCandidate = originalLocalPath[index];
|
|
2683
|
-
const port = graph.ports.find(
|
|
2684
|
-
(candidatePort) => candidatePort.portId === originalCandidate.port.portId
|
|
2685
|
-
);
|
|
2686
|
-
const nextRegion = port.region1 === currentRegion ? port.region2 : port.region1;
|
|
2687
|
-
path.push({
|
|
2688
|
-
port,
|
|
2689
|
-
g: originalCandidate.g,
|
|
2690
|
-
h: originalCandidate.h,
|
|
2691
|
-
f: originalCandidate.f,
|
|
2692
|
-
hops: index,
|
|
2693
|
-
ripRequired: originalCandidate.ripRequired,
|
|
2694
|
-
parent: index > 0 ? path[index - 1] : void 0,
|
|
2695
|
-
lastPort: index > 0 ? path[index - 1].port : void 0,
|
|
2696
|
-
lastRegion: index > 0 ? currentRegion : void 0,
|
|
2697
|
-
nextRegion
|
|
2698
|
-
});
|
|
2699
|
-
currentRegion = nextRegion;
|
|
2700
|
-
}
|
|
2701
|
-
return {
|
|
2702
|
-
connection: sectionRoute.sectionConnection,
|
|
2703
|
-
path,
|
|
2704
|
-
requiredRip: sectionRoute.globalRoute.requiredRip
|
|
2705
|
-
};
|
|
2706
|
-
};
|
|
2707
|
-
|
|
2708
|
-
// lib/HyperGraphSectionOptimizer/sections/getRouteSectionSpan.ts
|
|
2709
|
-
var getRouteSectionSpan = (route, sectionRegionIds) => {
|
|
2710
|
-
let startIndex = -1;
|
|
2711
|
-
let endIndex = -1;
|
|
2712
|
-
for (let i = 0; i < route.path.length; i++) {
|
|
2713
|
-
const candidate = route.path[i];
|
|
2714
|
-
const touchesSection = candidate.lastRegion && sectionRegionIds.has(candidate.lastRegion.regionId) || candidate.nextRegion && sectionRegionIds.has(candidate.nextRegion.regionId);
|
|
2715
|
-
if (!touchesSection) continue;
|
|
2716
|
-
if (startIndex === -1) startIndex = i;
|
|
2717
|
-
endIndex = i;
|
|
2718
|
-
}
|
|
2719
|
-
if (startIndex === -1) return null;
|
|
2720
|
-
return { startIndex, endIndex };
|
|
2721
|
-
};
|
|
2722
|
-
|
|
2723
|
-
// lib/HyperGraphSectionOptimizer/sections/getSectionRegionIds.ts
|
|
2724
|
-
var getSectionRegionIds = ({
|
|
2725
|
-
centralRegion,
|
|
2726
|
-
expansionHopsFromCentralRegion
|
|
2727
|
-
}) => {
|
|
2728
|
-
const sectionRegionIds = /* @__PURE__ */ new Set([centralRegion.regionId]);
|
|
2729
|
-
const queue = [
|
|
2730
|
-
{ region: centralRegion, hops: 0 }
|
|
2731
|
-
];
|
|
2732
|
-
while (queue.length > 0) {
|
|
2733
|
-
const { region, hops } = queue.shift();
|
|
2734
|
-
if (hops >= expansionHopsFromCentralRegion + 1) continue;
|
|
2735
|
-
for (const port of region.ports) {
|
|
2736
|
-
const nextRegion = port.region1 === region ? port.region2 : port.region1;
|
|
2737
|
-
if (sectionRegionIds.has(nextRegion.regionId)) continue;
|
|
2738
|
-
sectionRegionIds.add(nextRegion.regionId);
|
|
2739
|
-
queue.push({ region: nextRegion, hops: hops + 1 });
|
|
2740
|
-
}
|
|
2741
|
-
}
|
|
2742
|
-
return sectionRegionIds;
|
|
2743
|
-
};
|
|
2744
|
-
|
|
2745
|
-
// lib/HyperGraphSectionOptimizer/sections/getSectionOfHyperGraphAsHyperGraph.ts
|
|
2746
|
-
var getSectionOfHyperGraphAsHyperGraph = (input) => {
|
|
2747
|
-
const { graph, solvedRoutes, centralRegion, expansionHopsFromCentralRegion } = input;
|
|
2748
|
-
const sectionRegionIds = getSectionRegionIds({
|
|
2749
|
-
graph,
|
|
2750
|
-
centralRegion,
|
|
2751
|
-
expansionHopsFromCentralRegion
|
|
2752
|
-
});
|
|
2753
|
-
const clonedRegionMap = /* @__PURE__ */ new Map();
|
|
2754
|
-
const boundaryRegionMap = /* @__PURE__ */ new Map();
|
|
2755
|
-
const clonedPorts = [];
|
|
2756
|
-
for (const region of graph.regions) {
|
|
2757
|
-
if (!sectionRegionIds.has(region.regionId)) continue;
|
|
2758
|
-
clonedRegionMap.set(region.regionId, {
|
|
2759
|
-
regionId: region.regionId,
|
|
2760
|
-
ports: [],
|
|
2761
|
-
d: region.d ? structuredClone(region.d) : region.d,
|
|
2762
|
-
assignments: []
|
|
2763
|
-
});
|
|
2764
|
-
}
|
|
2765
|
-
for (const port of graph.ports) {
|
|
2766
|
-
const region1InSection = sectionRegionIds.has(port.region1.regionId);
|
|
2767
|
-
const region2InSection = sectionRegionIds.has(port.region2.regionId);
|
|
2768
|
-
if (!region1InSection && !region2InSection) continue;
|
|
2769
|
-
if (region1InSection && region2InSection) {
|
|
2770
|
-
const clonedPort2 = {
|
|
2771
|
-
portId: port.portId,
|
|
2772
|
-
region1: clonedRegionMap.get(port.region1.regionId),
|
|
2773
|
-
region2: clonedRegionMap.get(port.region2.regionId),
|
|
2774
|
-
d: port.d
|
|
2775
|
-
};
|
|
2776
|
-
clonedPort2.region1.ports.push(clonedPort2);
|
|
2777
|
-
clonedPort2.region2.ports.push(clonedPort2);
|
|
2778
|
-
clonedPorts.push(clonedPort2);
|
|
2779
|
-
continue;
|
|
2780
|
-
}
|
|
2781
|
-
const insideRegion = region1InSection ? port.region1 : port.region2;
|
|
2782
|
-
const boundaryRegion = getOrCreateBoundaryRegion({
|
|
2783
|
-
port,
|
|
2784
|
-
boundaryRegionMap
|
|
2785
|
-
});
|
|
2786
|
-
const clonedPort = {
|
|
2787
|
-
portId: port.portId,
|
|
2788
|
-
region1: clonedRegionMap.get(insideRegion.regionId),
|
|
2789
|
-
region2: boundaryRegion,
|
|
2790
|
-
d: port.d
|
|
2791
|
-
};
|
|
2792
|
-
clonedPort.region1.ports.push(clonedPort);
|
|
2793
|
-
clonedPort.region2.ports.push(clonedPort);
|
|
2794
|
-
clonedPorts.push(clonedPort);
|
|
2795
|
-
}
|
|
2796
|
-
const sectionGraph = {
|
|
2797
|
-
regions: [...clonedRegionMap.values(), ...boundaryRegionMap.values()],
|
|
2798
|
-
ports: clonedPorts
|
|
2799
|
-
};
|
|
2800
|
-
const sectionRoutes = [];
|
|
2801
|
-
const sectionConnections = [];
|
|
2802
|
-
const sectionRegionMap = new Map(
|
|
2803
|
-
sectionGraph.regions.map((region) => [region.regionId, region])
|
|
2804
|
-
);
|
|
2805
|
-
for (const solvedRoute of solvedRoutes) {
|
|
2806
|
-
const span = getRouteSectionSpan(solvedRoute, sectionRegionIds);
|
|
2807
|
-
if (!span) continue;
|
|
2808
|
-
const startCandidate = solvedRoute.path[span.startIndex];
|
|
2809
|
-
const endCandidate = solvedRoute.path[span.endIndex];
|
|
2810
|
-
let startRegionId;
|
|
2811
|
-
let startRegion;
|
|
2812
|
-
if (sectionRegionIds.has(solvedRoute.connection.startRegion.regionId)) {
|
|
2813
|
-
startRegionId = solvedRoute.connection.startRegion.regionId;
|
|
2814
|
-
startRegion = sectionRegionMap.get(startRegionId);
|
|
2815
|
-
} else {
|
|
2816
|
-
const boundaryRegion = getOrCreateBoundaryRegion({
|
|
2817
|
-
port: startCandidate.port,
|
|
2818
|
-
boundaryRegionMap
|
|
2819
|
-
});
|
|
2820
|
-
startRegionId = boundaryRegion.regionId;
|
|
2821
|
-
startRegion = boundaryRegion;
|
|
2822
|
-
if (!sectionRegionMap.has(startRegionId)) {
|
|
2823
|
-
sectionRegionMap.set(startRegionId, boundaryRegion);
|
|
2824
|
-
}
|
|
2825
|
-
}
|
|
2826
|
-
let endRegionId;
|
|
2827
|
-
let endRegion;
|
|
2828
|
-
if (sectionRegionIds.has(solvedRoute.connection.endRegion.regionId)) {
|
|
2829
|
-
endRegionId = solvedRoute.connection.endRegion.regionId;
|
|
2830
|
-
endRegion = sectionRegionMap.get(endRegionId);
|
|
2831
|
-
} else {
|
|
2832
|
-
const boundaryRegion = getOrCreateBoundaryRegion({
|
|
2833
|
-
port: endCandidate.port,
|
|
2834
|
-
boundaryRegionMap
|
|
2835
|
-
});
|
|
2836
|
-
endRegionId = boundaryRegion.regionId;
|
|
2837
|
-
endRegion = boundaryRegion;
|
|
2838
|
-
if (!sectionRegionMap.has(endRegionId)) {
|
|
2839
|
-
sectionRegionMap.set(endRegionId, boundaryRegion);
|
|
2840
|
-
}
|
|
2841
|
-
}
|
|
2842
|
-
if (!startRegion) {
|
|
2843
|
-
console.error(
|
|
2844
|
-
`[getSectionOfHyperGraphAsHyperGraph] CRITICAL ERROR: startRegion not found!`
|
|
2845
|
-
);
|
|
2846
|
-
console.error(` Looking for: ${startRegionId}`);
|
|
2847
|
-
console.error(
|
|
2848
|
-
` Route connection: ${solvedRoute.connection.connectionId}`
|
|
2849
|
-
);
|
|
2850
|
-
console.error(
|
|
2851
|
-
` Original startRegion: ${solvedRoute.connection.startRegion.regionId}`
|
|
2852
|
-
);
|
|
2853
|
-
console.error(` startCandidate port: ${startCandidate.port.portId}`);
|
|
2854
|
-
console.error(
|
|
2855
|
-
` Available regions in sectionRegionMap:`,
|
|
2856
|
-
Array.from(sectionRegionMap.keys())
|
|
2857
|
-
);
|
|
2858
|
-
throw new Error(
|
|
2859
|
-
`startRegion ${startRegionId} not found in sectionRegionMap`
|
|
2860
|
-
);
|
|
2861
|
-
}
|
|
2862
|
-
if (!endRegion) {
|
|
2863
|
-
console.error(
|
|
2864
|
-
`[getSectionOfHyperGraphAsHyperGraph] CRITICAL ERROR: endRegion not found!`
|
|
2865
|
-
);
|
|
2866
|
-
console.error(` Looking for: ${endRegionId}`);
|
|
2867
|
-
console.error(
|
|
2868
|
-
` Route connection: ${solvedRoute.connection.connectionId}`
|
|
2869
|
-
);
|
|
2870
|
-
console.error(
|
|
2871
|
-
` Original endRegion: ${solvedRoute.connection.endRegion.regionId}`
|
|
2872
|
-
);
|
|
2873
|
-
console.error(` endCandidate port: ${endCandidate.port.portId}`);
|
|
2874
|
-
console.error(
|
|
2875
|
-
` Available regions in sectionRegionMap:`,
|
|
2876
|
-
Array.from(sectionRegionMap.keys())
|
|
2877
|
-
);
|
|
2878
|
-
throw new Error(`endRegion ${endRegionId} not found in sectionRegionMap`);
|
|
2879
|
-
}
|
|
2880
|
-
const sectionConnection = {
|
|
2881
|
-
connectionId: solvedRoute.connection.connectionId,
|
|
2882
|
-
mutuallyConnectedNetworkId: solvedRoute.connection.mutuallyConnectedNetworkId,
|
|
2883
|
-
startRegion,
|
|
2884
|
-
endRegion
|
|
2885
|
-
};
|
|
2886
|
-
const rawPath = solvedRoute.path.slice(span.startIndex, span.endIndex + 1);
|
|
2887
|
-
const sectionRouteBase = {
|
|
2888
|
-
globalRoute: solvedRoute,
|
|
2889
|
-
globalConnection: solvedRoute.connection,
|
|
2890
|
-
sectionConnection,
|
|
2891
|
-
sectionStartIndex: span.startIndex,
|
|
2892
|
-
sectionEndIndex: span.endIndex
|
|
2893
|
-
};
|
|
2894
|
-
sectionRoutes.push({
|
|
2895
|
-
...sectionRouteBase,
|
|
2896
|
-
canRemainFixedInSectionSolve: rawPath.every(
|
|
2897
|
-
(candidate) => sectionGraph.ports.some(
|
|
2898
|
-
(port) => port.portId === candidate.port.portId
|
|
2899
|
-
)
|
|
2900
|
-
),
|
|
2901
|
-
sectionRoute: sliceSolvedRouteIntoLocalSection({
|
|
2902
|
-
sectionRoute: sectionRouteBase,
|
|
2903
|
-
graph: sectionGraph
|
|
2904
|
-
})
|
|
2905
|
-
});
|
|
2906
|
-
sectionConnections.push(sectionConnection);
|
|
2907
|
-
}
|
|
2908
|
-
return {
|
|
2909
|
-
centralRegionId: centralRegion.regionId,
|
|
2910
|
-
sectionRegionIds,
|
|
2911
|
-
graph: sectionGraph,
|
|
2912
|
-
connections: sectionConnections,
|
|
2913
|
-
sectionRoutes
|
|
2914
|
-
};
|
|
2915
|
-
};
|
|
2916
|
-
|
|
2917
3056
|
// lib/HyperGraphSectionOptimizer/HyperGraphSectionOptimizer.ts
|
|
2918
3057
|
var HyperGraphSectionOptimizer = class extends BaseSolver2 {
|
|
2919
3058
|
constructor(input) {
|
|
@@ -24596,6 +24735,7 @@ export {
|
|
|
24596
24735
|
createConvexViaGraphFromXYConnections,
|
|
24597
24736
|
createGraphWithConnectionsFromBaseGraph,
|
|
24598
24737
|
createViaGraphWithConnections,
|
|
24738
|
+
extractSectionOfHyperGraph,
|
|
24599
24739
|
generateConvexViaTopologyRegions,
|
|
24600
24740
|
generateDefaultViaTopologyRegions,
|
|
24601
24741
|
generateJumperGrid,
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tscircuit/hypergraph",
|
|
3
3
|
"main": "dist/index.js",
|
|
4
|
-
"version": "0.0.
|
|
4
|
+
"version": "0.0.67",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"start": "cosmos",
|
|
@@ -26,6 +26,7 @@
|
|
|
26
26
|
"high-density-dataset-z04": "git+https://github.com/tscircuit/high-density-dataset-z04.git#b9128ed52f5a50102b6526319be1d4ec33dca2c2",
|
|
27
27
|
"react-cosmos": "^7.1.0",
|
|
28
28
|
"react-cosmos-plugin-vite": "^7.1.0",
|
|
29
|
+
"stack-svgs": "^0.0.1",
|
|
29
30
|
"transformation-matrix": "^3.1.0",
|
|
30
31
|
"tsup": "^8.5.1"
|
|
31
32
|
},
|