@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 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/HyperGraphSolver.ts
1500
- import { BaseSolver } from "@tscircuit/solver-utils";
1501
-
1502
- // lib/convertSerializedConnectionsToConnections.ts
1503
- var convertSerializedConnectionsToConnections = (inputConnections, graph) => {
1504
- const connections = [];
1505
- for (const inputConn of inputConnections) {
1506
- if ("startRegionId" in inputConn) {
1507
- connections.push({
1508
- connectionId: inputConn.connectionId,
1509
- mutuallyConnectedNetworkId: inputConn.connectionId,
1510
- startRegion: graph.regions.find(
1511
- (region) => region.regionId === inputConn.startRegionId
1512
- ),
1513
- endRegion: graph.regions.find(
1514
- (region) => region.regionId === inputConn.endRegionId
1515
- )
1516
- });
1517
- } else {
1518
- connections.push(inputConn);
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 connections;
1528
+ return boundaryRegion;
1522
1529
  };
1523
1530
 
1524
- // lib/convertSerializedHyperGraphToHyperGraph.ts
1525
- var convertSerializedHyperGraphToHyperGraph = (inputGraph) => {
1526
- if (inputGraph.ports.length > 0 && "region1" in inputGraph.ports[0] && typeof inputGraph.ports[0].region1 === "object") {
1527
- return inputGraph;
1528
- }
1529
- const portMap = /* @__PURE__ */ new Map();
1530
- const regionMap = /* @__PURE__ */ new Map();
1531
- for (const region of inputGraph.regions) {
1532
- const { assignments: _, ...regionWithoutAssignments } = region;
1533
- regionMap.set(region.regionId, {
1534
- ...regionWithoutAssignments,
1535
- d: regionWithoutAssignments.d ? structuredClone(regionWithoutAssignments.d) : regionWithoutAssignments.d,
1536
- ports: [],
1537
- assignments: void 0
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
- ports: Array.from(portMap.values()),
1555
- regions: Array.from(regionMap.values())
1559
+ connection: sectionRoute.sectionConnection,
1560
+ path,
1561
+ requiredRip: sectionRoute.globalRoute.requiredRip
1556
1562
  };
1557
1563
  };
1558
1564
 
1559
- // lib/PriorityQueue.ts
1560
- var PriorityQueue = class {
1561
- // Store the heap as an array. Index 0 is the root (highest priority/smallest 'f').
1562
- heap = [];
1563
- maxSize;
1564
- /**
1565
- * Creates a new Priority Queue.
1566
- * @param nodes An optional initial array of nodes to populate the queue.
1567
- * @param maxSize The maximum number of elements the queue can hold. Defaults to 10,000.
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
- * Returns the node with the highest priority (smallest 'f') without removing it.
1592
- * Returns null if the queue is empty.
1593
- * @returns The highest priority node or null.
1594
- */
1595
- peek() {
1596
- if (this.isEmpty()) {
1597
- return null;
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
- * Returns up to N nodes with the highest priority (smallest 'f') without removing them.
1603
- * Nodes are returned sorted by priority (smallest 'f' first).
1604
- * @param count Maximum number of nodes to return.
1605
- * @returns Array of nodes sorted by priority.
1606
- */
1607
- peekMany(count) {
1608
- return [...this.heap].sort((a, b) => a.f - b.f).slice(0, count);
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
- * Removes and returns the node with the highest priority (smallest 'f').
1612
- * Returns null if the queue is empty.
1613
- * Maintains the heap property.
1614
- * @returns The highest priority node or null.
1615
- */
1616
- dequeue() {
1617
- if (this.isEmpty()) {
1618
- return null;
1619
- }
1620
- const minNode = this.heap[0];
1621
- const lastNode = this.heap.pop();
1622
- if (this.heap.length === 0 && lastNode !== void 0) {
1623
- return minNode;
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
- return minNode;
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
- * Adds a new node to the queue.
1633
- * Maintains the heap property.
1634
- * If the queue is full (at maxSize), the node is not added.
1635
- * @param node The node to add.
1636
- */
1637
- enqueue(node) {
1638
- if (this.heap.length >= this.maxSize) {
1639
- return;
1640
- }
1641
- this.heap.push(node);
1642
- this._siftUp(this.heap.length - 1);
1643
- }
1644
- // --- Private Helper Methods ---
1645
- /**
1646
- * Moves the node at the given index up the heap to maintain the heap property.
1647
- * @param index The index of the node to sift up.
1648
- */
1649
- _siftUp(index) {
1650
- let currentIndex = index;
1651
- while (currentIndex > 0) {
1652
- const parentIndex = this._parentIndex(currentIndex);
1653
- if (this.heap[parentIndex].f <= this.heap[currentIndex].f) {
1654
- break;
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
- * Moves the node at the given index down the heap to maintain the heap property.
1662
- * @param index The index of the node to sift down.
1663
- */
1664
- _siftDown(index) {
1665
- let currentIndex = index;
1666
- const heapSize = this.heap.length;
1667
- while (true) {
1668
- const leftChildIndex = this._leftChildIndex(currentIndex);
1669
- const rightChildIndex = this._rightChildIndex(currentIndex);
1670
- let smallestIndex = currentIndex;
1671
- if (leftChildIndex < heapSize && this.heap[leftChildIndex].f < this.heap[smallestIndex].f) {
1672
- smallestIndex = leftChildIndex;
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
- * Swaps two elements in the heap array.
1687
- * @param i Index of the first element.
1688
- * @param j Index of the second element.
1689
- */
1690
- _swap(i, j) {
1691
- ;
1692
- [this.heap[i], this.heap[j]] = [this.heap[j], this.heap[i]];
1693
- }
1694
- /** Calculates the parent index of a node. */
1695
- _parentIndex(index) {
1696
- return Math.floor((index - 1) / 2);
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
- /** Calculates the left child index of a node. */
1699
- _leftChildIndex(index) {
1700
- return 2 * index + 1;
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
- /** Calculates the right child index of a node. */
1703
- _rightChildIndex(index) {
1704
- return 2 * index + 2;
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/solvedRoutes.ts
1709
- var clearAssignmentsFromGraph = (graph) => {
1710
- for (const region of graph.regions) {
1711
- region.assignments = [];
1712
- }
1713
- for (const port of graph.ports) {
1714
- port.assignment = void 0;
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
- var commitSolvedRoutes = ({
1718
- graph,
1719
- connections,
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
- connections.map((connection) => [connection.connectionId, connection])
1838
+ convertSerializedConnectionsToConnections(
1839
+ inputSolvedRoutes.map((route) => route.connection),
1840
+ graph
1841
+ ).map((connection) => [connection.connectionId, connection])
1728
1842
  );
1729
- const committedSolvedRoutes = solvedRoutes.map((solvedRoute) => {
1843
+ return inputSolvedRoutes.map((inputSolvedRoute) => {
1730
1844
  const path = [];
1731
- for (const originalCandidate of solvedRoute.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
+ }
1732
1852
  const candidate = {
1733
- port: portMap.get(originalCandidate.port.portId),
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.lastPort) {
1741
- candidate.lastPort = portMap.get(originalCandidate.lastPort.portId);
1860
+ if (originalCandidate.lastPortId) {
1861
+ candidate.lastPort = getRequiredPort(
1862
+ portMap,
1863
+ originalCandidate.lastPortId,
1864
+ inputSolvedRoute.connection.connectionId
1865
+ );
1742
1866
  }
1743
- if (originalCandidate.lastRegion) {
1744
- candidate.lastRegion = regionMap.get(
1745
- originalCandidate.lastRegion.regionId
1867
+ if (originalCandidate.lastRegionId) {
1868
+ candidate.lastRegion = getRequiredRegion(
1869
+ regionMap,
1870
+ originalCandidate.lastRegionId,
1871
+ inputSolvedRoute.connection.connectionId
1746
1872
  );
1747
1873
  }
1748
- if (originalCandidate.nextRegion) {
1749
- candidate.nextRegion = regionMap.get(
1750
- originalCandidate.nextRegion.regionId
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: connectionMap.get(solvedRoute.connection.connectionId),
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.65",
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
  },