tscircuit / tscircuit/schematic-trace-solver
bug: a single oscillating net pair aborts TraceOverlapShiftSolver and leaves independent cross-net overlaps unresolved
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 13
- Forks
- 314
- Avg merge
- 9h 3m
- Merged PRs (30d)
- 132
Description
TraceOverlapShiftSolver treats its A -> B -> A oscillation guard as a reason to stop the entire solve. The first net pair that oscillates aborts the whole pass, so every other cross-net overlap still queued at that moment is silently left in the output, even though those pairs are independent and would have been corrected in the next few iterations.
Sub-solver
lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts, in _step():
if (this.returnsToPreviousTraceState(nextTraceState)) {
this.activeSubSolver = null
this.solved = true // <- ends the whole solver, not just this net pair
return
}
Reproduction
Minimized from tests/repros/assets/board-1273-trace-overlap-cycle.input.json (74 chips -> 5 chips, 14 pins). Two cross-net collinear overlaps survive the shift solver: GND/VBUS and RTS/DTR. Only the GND/VBUS pair actually oscillates.
{
"chips": [
{
"chipId": "schematic_component_23",
"center": {
"x": 11.084375,
"y": -5.325
},
"width": 2.3000000000000007,
"height": 3.2000000000000006,
"pins": [
{
"pinId": "schematic_port_75",
"x": 9.934375,
"y": -4.325
},
{
"pinId": "schematic_port_79",
"x": 9.934375,
"y": -5.125
},
{
"pinId": "schematic_port_80",
"x": 9.934375,
"y": -5.325
},
{
"pinId": "schematic_port_96",
"x": 12.234375,
"y": -5.025
},
{
"pinId": "schematic_port_100",
"x": 12.234375,
"y": -4.2250000000000005
},
{
"pinId": "schematic_port_101",
"x": 12.234375,
"y": -4.025
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_26",
"center": {
"x": 7.629375,
"y": -3.9250000000000007
},
"width": 0.7800000000000002,
"height": 0.7600000000000011,
"pins": [
{
"pinId": "schematic_port_106",
"x": 7.564375,
"y": -4.3050000000000015,
"_facingDirection": "y-"
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_27",
"center": {
"x": 9.221875,
"y": -5.55
},
"width": 1.205,
"height": 0.5999999999999996,
"pins": [
{
"pinId": "schematic_port_108",
"x": 8.944374999999999,
"y": -5.25,
"_facingDirection": "y+"
},
{
"pinId": "schematic_port_109",
"x": 8.944374999999999,
"y": -5.85,
"_facingDirection": "y-"
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_28",
"center": {
"x": 9.221875,
"y": -4.23
},
"width": 1.205,
"height": 0.6000000000000014,
"pins": [
{
"pinId": "schematic_port_111",
"x": 8.944374999999999,
"y": -3.9299999999999997
}
],
"sectionId": "USB to UART"
},
{
"chipId": "schematic_component_32",
"center": {
"x": 15.769374999999998,
"y": -4.724999999999999
},
"width": 2,
"height": 0.8000000000000007,
"pins": [
{
"pinId": "schematic_port_118",
"x": 14.769374999999998,
"y": -4.524999999999999
},
{
"pinId": "schematic_port_119",
"x": 14.769374999999998,
"y": -4.724999999999999
},
{
"pinId": "schematic_port_121",
"x": 16.769374999999997,
"y": -4.924999999999999
},
{
"pinId": "schematic_port_122",
"x": 16.769374999999997,
"y": -4.724999999999999
}
],
"sectionId": "USB to UART"
}
],
"directConnections": [
{
"netId": ".R5 > .pin1 to .U6 > .VBUS",
"pinIds": [
"schematic_port_108",
"schematic_port_80"
]
}
],
"netConnections": [
{
"netId": "GND",
"isGround": true,
"netLabelWidth": 0.42,
"netLabelHeight": 0.48,
"pinIds": [
"schematic_port_75",
"schematic_port_101",
"schematic_port_106",
"schematic_port_109"
]
},
{
"netId": "VBUS",
"netLabelWidth": 0.42,
"netLabelHeight": 0.6,
"pinIds": [
"schematic_port_79",
"schematic_port_111"
]
},
{
"netId": "RTS",
"netLabelWidth": 0.48,
"pinIds": [
"schematic_port_96",
"schematic_port_118",
"schematic_port_122"
]
},
{
"netId": "DTR",
"netLabelWidth": 0.48,
"pinIds": [
"schematic_port_100",
"schematic_port_119",
"schematic_port_121"
]
}
],
"textBoxes": [],
"availableNetLabelOrientations": {
"GND": [
"y-"
],
"VBUS": [
"y+"
],
"RTS": [
"x-",
"x+"
],
"DTR": [
"x-",
"x+"
]
},
"maxMspPairDistance": 8,
"_hideRatsNet": false
}
const solver = new SchematicTracePipelineSolver(inputProblem)
solver.solve()
// inspect solver.traceOverlapShiftSolver.correctedTraceMap for
// cross-net segments that are collinear and overlapping
Observed
The solver stops at iteration 9 with solved === true, and two distinct cross-net pairs still overlap collinearly:
connectivity_net0 ~ connectivity_net1 (GND / VBUS, the oscillating pair)
connectivity_net3 ~ connectivity_net4 (RTS / DTR, independent)
The RTS/DTR traces share an exact coordinate over a positive-length span, so they render as one wire.
On the full board-1273 fixture the same abort leaves 6 unresolved cross-net pairs after 27 iterations.
Expected
Oscillation between two nets should suspend only that net pair. Independent overlaps should keep being corrected until no correctable overlap remains. For this input only connectivity_net0 ~ connectivity_net1 should remain; RTS/DTR should be separated.
On board-1273 this takes the unresolved pairs from 6 down to 1 (the single genuinely oscillating pair), with the same 135 traces routed and no trace added or dropped.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start in lib/solvers/TraceOverlapShiftSolver/TraceOverlapShiftSolver.ts, especially _step() and returnsToPreviousTraceState(), then run the provided board-1273 reproduction through SchematicTracePipelineSolver. Verify that an oscillating GND/VBUS pair no longer ends the entire pass and that the independent RTS/DTR overlap is corrected. Done means only the genuinely oscillating pair remains, with 135 traces and no trace added or dropped.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- computer-graphics
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Active
- Clarity
- Clearly specified
- Newbie friendliness
- 78/100