Acyclic sink bridges (LNG_SINK_BRIDGES, off by default; measured, not adopted) - #92
adamjohnwright wants to merge 4 commits into
Conversation
A dissociation sink (a released subunit minted as a readout handle) gains an OR edge to each consuming copy of the same entity, but only where that copy cannot reach the sink -- so no cycle is closed and the cycle census is unchanged. Bridging sinks was measured harmful twice on catalogs whose giant components were welded by our own edges and without a cycle guard; on the fixed catalog the curator oracle simulates Interferon alpha/beta 293 -> 631 connected routes of 685 (13 bridges) and Mitotic G1 530 -> 705 of 960 (234), the two pathways holding 686 of the benchmark's 1,526 no_path errors. Tests: tests/test_sink_bridges.py (6). Measurement: deltasignal specs/019. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…ast sinks Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…itter Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…etermined Adversarial review found the intervention was not the one the docstring describes. Two defects, both now fixed and mutation-tested: 1. The consumer filter `out_deg[c] > 0` read the same dict the emitter increments, so once a sink received a bridge it became an eligible "consuming copy" for every later sink of the same entity. Measured on the shipped catalog: 24,967 of 36,125 edges (69%) pointed at another sink and consumed nothing -- concentrated in the pathways that lost (ROBO 77%, Mitotic G1 93%) while the one that gained was 7%. Eligibility is now decided against a pre-emitter snapshot; the genuine count (~11.2k) matches the simulation (10,547) that motivated the design, which the old writeup had wrongly explained as pre-dedup inflation. 2. Sinks were visited in `sorted()` order over uuid4 labels, so the emitted SET (not just its order) was a fresh random draw per regeneration -- the generator had the solver's label-dependence one layer up. Ordering is now by (stable id, first appearance in the edge list), both functions of the Reactome data. Also: the fan-out statistic now records capped sinks (the cap-8 run hid 1,290 from its own log), `skipped` is counted after the cap check, and a negative LNG_SINK_BRIDGE_MAX_FANOUT is an error instead of silently capping everything. Tests: 12 (was 7). The three guarantees the review showed were untested -- no sink is ever a bridge target, a bridge can make a later candidate cycle-closing, and visit order is data-determined -- each now fail their mutation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Closing unmerged, per the flag-expiry policy in deltasignal specs/020-variant-node-sharing/cleanup-plan.md: a flag expires once its question is answered, and the spec keeps the evidence rather than the code. The question is answered. Three interventions in this family were measured on the current (unwelded) catalog and none paid: all acyclic sink bridges (11,069 edges) held-out -44, p 0.59; fan-out capped at 8 (3,416 edges) held-out -21, p 0.87; the earlier solve-time equivalent -73 and -77. The mechanism is real and was verified -- bridging cuts severed curator root-to-terminal pairs from 47.5% to 37.9% -- but it does not convert into accuracy, because a released subunit is one of a median-1 / p90-8 / max-160 fan-out and the bridge routes signal into all of them. Closed rather than merged because git diff main...feat/sink-bridges is 293 insertions and 0 deletions. The branch is purely additive, so there is nothing on main to delete and no shared-code fix to salvage; merging would land a permanently-off emitter plus 12 tests pinning behaviour we have decided against, and the solver has no sink_bridge handling at all. Preserved on main in deltasignal specs/019-sink-bridges/research.md: the numbers above, the oracle simulation, the fan-out distribution, corrections C1-C4, and the two real defects this branch's review found -- a consumer-set cascade that made 69% of emitted edges point at another sink, and a uuid4-ordering non-determinism that made the emitted set a random draw per regeneration. One live finding is NOT closed by this. Interferon alpha/beta was +100 fixed and 0 broken, the largest single-pathway gain from any structural change tried. It is recorded in specs/019 as unclaimed. The read is that it needs copy identity (specs/005), one node per entity per reaction, rather than edges bolted onto duplicate sinks. Reopen against that, not against this emitter. |
A dissociation sink (a released subunit minted as a readout handle) gains an OR edge to each consuming copy of the same entity — only where that copy cannot reach the sink, so no cycle is closed.
LNG_SINK_BRIDGE_MAX_FANOUT=nskips broadcast sinks.The guard works exactly as intended: on the fixed catalog, cyclic components 210 → 210, nodes in cycles 8,407 → 8,407, largest component 675 — with 36,125 bridges added (4,003 at fan-out ≤ 8).
Measured and not adopted (deltasignal specs/019, pre-registered): held-out −6 (p 0.78) uncapped, +23 (p 0.20) capped; false change +171/+150; experimental 0 / −15. Interferon α/β +100 (100 fixed, 0 broke) and Mitotic G1 +35 against ROBO −43, PDGF −13 and 176 new false changes in 17 pathways. Third measurement of sink bridging and the first with the cycle objection removed — that objection was not what was wrong with it.
Merged off by default so the flag and its measurement exist and the question needn't be re-opened a fourth time. Tests:
tests/test_sink_bridges.py(7).🤖 Generated with Claude Code