python-fm-index-bwt-backward-search
Done. The deliverable is ~/SOLUTION.md (self-contained: title, root-cause analysis, exact fix with the complete module, verification section), backed by two working artifacts:
~/genome_fm.py — 317-line FM-index module (pure-Python SA-IS suffix array + optional pydivsufsort fast path → BWT → rank checkpoints → backward search)~/verify.py — full test harness; python3 verify.py passes all checksCounts are silently corrupted by any of five convention breaks, all of which are off-by-one at checkpoint/LF boundaries:
cp[k] built "after" seeing BWT[k·stride]) — the tail scan then double-counts/skips the boundary char,(i-1)//stride instead of i//stride),N//stride and scan to N (BWT length is n+1, sentinel included),C['A']=1, not 0),i rank, shared with the query loop.Why repeats expose it: the interval update feeds lo,hi back as rank arguments, so one shifted checkpoint propagates; on random text the damage is hidden (±1, 45% of my demo queries wrong but "plausible"), while on telomeric ("TTAGGG")*500 the same one-line bug corrupts 91% of queries (e.g. 499 → 492). I implemented that buggy variant explicitly to demonstrate it, then fixed the module to pass everything.
SA[LF(i)] = (SA[i]-1) mod N for every position; boundary ranks at 0,1,S-1,S,S+1,N-1,N equal direct scanspython3 genome_fm.py < q.txt (line 1 = reference, one pattern per line) → counts per lineOne caveat found while verifying: Python's str.count is non-overlapping, so it is not a valid oracle on repeats ("AAA" has 2 occurrences of "AA", str.count says 1) — the harness uses an overlapping naive counter as ground truth.
# Evidence - Problem class: python-fm-index-bwt-backward-search - Model: openrouter/deepseek/deepseek-v4-flash-0731 - Solved: 2026-09-06T04:15:58.053Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Build an FM-index (Burrows-Wheeler Transform + suffix array + rank checkpoints) over a reference genome string of length up to 1e7 over {A,C,G,T,N}, then answer exact-match counting queries: for each of up to 1e5 patterns of length 1..1000, return occurrence counts in O(len(pattern)) via backward search with LF-mapping. Must handle highly repetitive genomes (telomeric satellite repeats) without memory blowup and agree with naive counting on small inputs. The crux is rank-checkpoint stride and LF-mapping off-by-one boundaries: a single mis-indexed checkpoint silently corrupts counts on repeated text.", "environment": "python3", "language": "python", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "python-fm-index-bwt-backward-search", "provider": "openrouter", "solved_at": "2026-09-06T04:15:58.053Z", "version": "3.11"}Done. The deliverable is ~/SOLUTION.md (self-contained: title, root-cause analysis, exact fix with the complete module, verification section), backed by two working artifacts:
~/genome_fm.py — 317-line FM-index module (pure-Python SA-IS suffix array + optional pydivsufsort fast path → BWT → rank checkpoints → backward search)~/verify.py — full test harness; python3 verify.py passes all checksCounts are silently corrupted by any of five convention breaks, all of which are off-by-one at checkpoint/LF boundaries:
cp[k] built "after" seeing BWT[k·stride]) — the tail scan then double-counts/skips the boundary char,(i-1)//stride instead of i//stride),N//stride and scan to N (BWT length is n+1, sentinel included),C['A']=1, not 0),i rank, shared with the query loop.Why repeats expose it: the interval update feeds lo,hi back as rank arguments, so one shifted checkpoint propagates; on random text the damage is hidden (±1, 45% of my demo queries wrong but "plausible"), while on telomeric ("TTAGGG")*500 the same one-line bug corrupts 91% of queries (e.g. 499 → 492). I implemented that buggy variant explicitly to demonstrate it, then fixed the module to pass everything.
SA[LF(i)] = (SA[i]-1) mod N for every position; boundary ranks at 0,1,S-1,S,S+1,N-1,N equal direct scanspython3 genome_fm.py < q.txt (line 1 = reference, one pattern per line) → counts per lineOne caveat found while verifying: Python's str.count is non-overlapping, so it is not a valid oracle on repeats ("AAA" has 2 occurrences of "AA", str.count says 1) — the harness uses an overlapping naive counter as ground truth.
# Evidence - Problem class: python-fm-index-bwt-backward-search - Model: openrouter/deepseek/deepseek-v4-flash-0731 - Solved: 2026-09-06T04:15:58.053Z - Verification: solution produced by pi in sandbox; see signatures.json
{"description": "Build an FM-index (Burrows-Wheeler Transform + suffix array + rank checkpoints) over a reference genome string of length up to 1e7 over {A,C,G,T,N}, then answer exact-match counting queries: for each of up to 1e5 patterns of length 1..1000, return occurrence counts in O(len(pattern)) via backward search with LF-mapping. Must handle highly repetitive genomes (telomeric satellite repeats) without memory blowup and agree with naive counting on small inputs. The crux is rank-checkpoint stride and LF-mapping off-by-one boundaries: a single mis-indexed checkpoint silently corrupts counts on repeated text.", "environment": "python3", "language": "python", "model": "openrouter/deepseek/deepseek-v4-flash-0731", "problem_class": "python-fm-index-bwt-backward-search", "provider": "openrouter", "solved_at": "2026-09-06T04:15:58.053Z", "version": "3.11"}