From ea4d90fde8cee44efa85cb8fa33384f8a1c74cd5 Mon Sep 17 00:00:00 2001 From: tungnguyentu Date: Thu, 14 May 2026 23:46:23 +0700 Subject: [PATCH] fix: prevent net-label-only nets from being routed as trace pairs (#79) Root cause: `getConnectivityMapsFromInputProblem` passed `directConnMap.netMap` by reference, so `netConnMap.addConnections()` mutated `directConnMap.netMap`. This caused `MspConnectionPairSolver` to queue net-only nets for routing. Fix: - Shallow-copy netMap when building `netConnMap` to prevent aliasing - Filter `queuedDcNetIds` to only include nets with at least one pin in a direct connection (net-only nets are handled by NetLabelPlacementSolver) Adds regression tests covering: net-only-only scenario produces 0 MSP pairs, direct connections still route, mixed scenario routes only direct nets. Co-Authored-By: Claude Sonnet 4.6 --- .../MspConnectionPairSolver.ts | 10 +- .../getConnectivityMapFromInputProblem.ts | 4 +- .../examples/__snapshots__/example01.snap.svg | 28 ++- .../examples/__snapshots__/example12.snap.svg | 71 ++++---- .../examples/__snapshots__/example13.snap.svg | 64 +++---- .../examples/__snapshots__/example14.snap.svg | 159 +++++++++--------- .../examples/__snapshots__/example15.snap.svg | 102 ++++++----- .../examples/__snapshots__/example16.snap.svg | 72 ++++---- .../examples/__snapshots__/example20.snap.svg | 58 +++---- .../examples/__snapshots__/example21.snap.svg | 156 ++++++++--------- ...pConnectionPairSolver_netLabelOnly.test.ts | 89 ++++++++++ .../MspConnectionPairSolver_repro1.test.ts | 3 +- 12 files changed, 429 insertions(+), 387 deletions(-) create mode 100644 tests/solvers/MspConnectionPairSolver/MspConnectionPairSolver_netLabelOnly.test.ts diff --git a/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts b/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts index 5aae3806..46dcc4d7 100644 --- a/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts +++ b/lib/solvers/MspConnectionPairSolver/MspConnectionPairSolver.ts @@ -75,7 +75,15 @@ export class MspConnectionPairSolver extends BaseSolver { } } - this.queuedDcNetIds = Object.keys(netConnMap.netMap) + // Only queue nets that have at least one pin in a direct connection. + // Net-only nets should be handled by NetLabelPlacementSolver, not routed. + const directPinIds = new Set( + inputProblem.directConnections.flatMap((dc) => dc.pinIds), + ) + this.queuedDcNetIds = Object.keys(netConnMap.netMap).filter((netId) => { + const ids = netConnMap.getIdsConnectedToNet(netId) as string[] + return ids.some((id) => directPinIds.has(id)) + }) } override getConstructorParams(): ConstructorParameters< diff --git a/lib/solvers/MspConnectionPairSolver/getConnectivityMapFromInputProblem.ts b/lib/solvers/MspConnectionPairSolver/getConnectivityMapFromInputProblem.ts index d3a098c3..32aa94f4 100644 --- a/lib/solvers/MspConnectionPairSolver/getConnectivityMapFromInputProblem.ts +++ b/lib/solvers/MspConnectionPairSolver/getConnectivityMapFromInputProblem.ts @@ -14,7 +14,9 @@ export const getConnectivityMapsFromInputProblem = ( ]) } - const netConnMap = new ConnectivityMap(directConnMap.netMap) + // Shallow copy prevents netConnMap.addConnections() from mutating + // directConnMap.netMap (they share the same object reference otherwise). + const netConnMap = new ConnectivityMap({ ...directConnMap.netMap }) for (const netConn of inputProblem.netConnections) { netConnMap.addConnections([[netConn.netId, ...netConn.pinIds]]) diff --git a/tests/examples/__snapshots__/example01.snap.svg b/tests/examples/__snapshots__/example01.snap.svg index 2614ba80..36b24459 100644 --- a/tests/examples/__snapshots__/example01.snap.svg +++ b/tests/examples/__snapshots__/example01.snap.svg @@ -41,16 +41,16 @@ y+" data-x="-4" data-y="0.5" cx="67.72277227722776" cy="245.14851485148515" r="3 y-" data-x="-4" data-y="-0.5" cx="67.72277227722776" cy="356.03960396039605" r="3" fill="hsl(3, 100%, 50%, 0.8)" /> - + - + - + + + + @@ -76,9 +76,6 @@ orientation: y-" data-x="-1.4" data-y="-0.7" cx="356.0396039603961" cy="378.2178 - - - @@ -90,18 +87,19 @@ orientation: y-" data-x="-1.4" data-y="-0.7" cx="356.0396039603961" cy="378.2178 +globalConnNetId: connectivity_net0" data-x="-1.1" data-y="0.42500000000000016" x="378.21782178217825" y="228.51485148514848" width="22.178217821782198" height="49.9009900990099" fill="#ef444466" stroke="#ef4444" stroke-width="0.009017857142857143" /> +globalConnNetId: connectivity_net1" data-x="-1.5" data-y="0" x="320" y="289.5049504950495" width="49.90099009900996" height="22.17821782178214" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.009017857142857143" /> + + + +globalConnNetId: connectivity_net2" data-x="-4" data-y="-0.726" x="56.63366336633669" y="356.1504950495049" width="22.17821782178214" height="49.90099009900996" fill="#00000066" stroke="#000000" stroke-width="0.009017857142857143" /> +globalConnNetId: connectivity_net3" data-x="3.75" data-y="-0.225" x="527.5217643644805" y="352.5014509576321" width="13.000580383052807" height="29.251305861868843" fill="#00000066" stroke="#000000" stroke-width="0.015383928571428571" /> + + + +globalConnNetId: connectivity_net3" data-x="4.1575" data-y="-1.725" x="554.0104468949507" y="450.0058038305282" width="13.000580383052693" height="29.251305861868843" fill="#00000066" stroke="#000000" stroke-width="0.015383928571428571" /> +globalConnNetId: connectivity_net4" data-x="1.475" data-y="0.225" x="379.6401625072548" y="323.25014509576323" width="13.000580383052807" height="29.251305861868843" fill="#ef444466" stroke="#ef4444" stroke-width="0.015383928571428571" /> +globalConnNetId: connectivity_net4" data-x="-1.301" data-y="-0.8490000000000001" x="199.19210679048172" y="393.0632617527569" width="13.000580383052807" height="29.251305861868843" fill="#ef444466" stroke="#ef4444" stroke-width="0.015383928571428571" /> +globalConnNetId: connectivity_net2" data-x="-2.125" data-y="0.225" x="145.6297156123041" y="323.25014509576323" width="13.000580383052835" height="29.251305861868843" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.015383928571428571" /> +globalConnNetId: connectivity_net0" data-x="-3.75" data-y="2.225" x="39.99999999999997" y="193.24434126523508" width="13.000580383052835" height="29.251305861868843" fill="#ef444466" stroke="#ef4444" stroke-width="0.015383928571428571" /> +globalConnNetId: connectivity_net0" data-x="2.2990000000000004" data-y="0.276" x="433.20255368543235" y="319.93499709808475" width="13.000580383052863" height="29.251305861868843" fill="#ef444466" stroke="#ef4444" stroke-width="0.015383928571428571" /> +globalConnNetId: connectivity_net1" data-x="1.96375" data-y="3.225" x="411.41033081834007" y="128.241439349971" width="13.000580383052807" height="29.25130586186887" fill="hsl(40, 100%, 50%, 0.35)" stroke="black" stroke-width="0.015383928571428571" />