FA-91651 / Digital signal filters / Open access
Linear-phase classifier swaps types 1 and 2 · case 01
An odd-length symmetric filter is labelled type 2.
ROOT CAUSE
The symmetric branch maps odd N to type 2 and even N to type 1.
VERIFIED REPAIR
Odd symmetric is type 1, even symmetric is type 2.
Unsuccessful approach: The attempted change swaps the antisymmetric mapping as well, mislabelling types 3 and 4.
Case contract
Input integer taps. Strip leading and trailing zeros ("degenerate" if all zero). The trimmed support of length N is type 1/2 if symmetric (odd/even N), type 3/4 if antisymmetric (odd/even N), otherwise not linear phase. Return {"type", "group_delay": leading zeros + (N-1)/2 as a fraction string} or both None.
Why this case matters
Linear-phase type determines which responses an FIR can realize (e.g. no highpass for type 2); misclassification picks the wrong design.
1 / The failure
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(x):
h = list(x)
lead = 0
while lead < len(h) and h[lead] == 0:
lead += 1
if lead == len(h):
return 'degenerate'
end = len(h)
while h[end - 1] == 0:
end -= 1
g = h[lead:end]
N = len(g)
sym = all(g[i] == g[N - 1 - i] for i in range(N))
anti = all(g[i] == -g[N - 1 - i] for i in range(N))
if sym:
typ = 2 if N % 2 else 1
elif anti:
typ = 3 if N % 2 else 4
else:
return {'type': None, 'group_delay': None}
return {'type': typ, 'group_delay': str(lead + Fraction(N - 1, 2))}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: type I', [1, 2, 1], {'type': 1, 'group_delay': '1'}], ['regression: type II', [1, 1], {'type': 2, 'group_delay': '1/2'}], ['repair check: type III zero centre', [1, 0, -1], {'type': 3, 'group_delay': '1'}], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}], ['control: all zero', [0, 0, 0], 'degenerate'], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}]], [['regression: trailing zeros', [1, 2, 1, 0], {'type': 1, 'group_delay': '1'}], ['regression: interior zero symmetric', [1, 0, 1], {'type': 1, 'group_delay': '1'}], ['repair check: type IV longer', [2, 1, -1, -2], {'type': 4, 'group_delay': '3/2'}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}], ['control: random linear phase 7', [0, 0, 0, 0, 0], 'degenerate'], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}]], [['regression: single tap', [5], {'type': 1, 'group_delay': '0'}], ['regression: padded interior zeros', [0, 2, 0, 0, 2], {'type': 2, 'group_delay': '5/2'}], ['repair check: random linear phase 1', [0, 2, -2, 0, 0, 0], {'type': 4, 'group_delay': '3/2'}], ['control: all zero', [0, 0, 0], 'degenerate'], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}]], [['regression: random linear phase 5', [0, 0, -3, -3, -2, -3, -3, 0], {'type': 1, 'group_delay': '4'}], ['regression: random linear phase 9', [0, 0, -1, -3, 3, -1, 3, -3, -1, 0, 0], {'type': 1, 'group_delay': '5'}], ['repair check: random linear phase 10', [0, 0, 0, -1, 1, 0], {'type': 4, 'group_delay': '7/2'}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}], ['control: random linear phase 7', [0, 0, 0, 0, 0], 'degenerate'], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}], ['control: all zero', [0, 0, 0], 'degenerate']], [['regression: random linear phase 15', [0, 0, 1, -1, -1, 1, 0, 0], {'type': 2, 'group_delay': '7/2'}], ['regression: random linear phase 17', [0, -3, 1, 3, -1, 3, 1, -3], {'type': 1, 'group_delay': '4'}], ['repair check: random linear phase 12', [-1, 1, -1, 1, 0, 0], {'type': 4, 'group_delay': '3/2'}], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: type I | {'group_delay': '1', 'type': 2} | {'group_delay': '1', 'type': 1} | Failed |
| regression: type II | {'group_delay': '1/2', 'type': 1} | {'group_delay': '1/2', 'type': 2} | Failed |
| repair check: type III zero centre | {'group_delay': '1', 'type': 3} | {'group_delay': '1', 'type': 3} | Passed |
| control: type III nonzero centre | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
| control: all zero | degenerate | degenerate | Passed |
| control: not linear phase | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
| control: random linear phase 2 | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
SHA-256 / 9f34d597bf4c6b0f51150460e153ff908eaa93df47846b4624d70beafbe152b5
2 / The unsuccessful fix
Exit 1"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(x):
h = list(x)
lead = 0
while lead < len(h) and h[lead] == 0:
lead += 1
if lead == len(h):
return 'degenerate'
end = len(h)
while h[end - 1] == 0:
end -= 1
g = h[lead:end]
N = len(g)
sym = all(g[i] == g[N - 1 - i] for i in range(N))
anti = all(g[i] == -g[N - 1 - i] for i in range(N))
if sym:
typ = 1 if N % 2 else 2
elif anti:
typ = 4 if N % 2 else 3
else:
return {'type': None, 'group_delay': None}
return {'type': typ, 'group_delay': str(lead + Fraction(N - 1, 2))}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: type I', [1, 2, 1], {'type': 1, 'group_delay': '1'}], ['regression: type II', [1, 1], {'type': 2, 'group_delay': '1/2'}], ['repair check: type III zero centre', [1, 0, -1], {'type': 3, 'group_delay': '1'}], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}], ['control: all zero', [0, 0, 0], 'degenerate'], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}]], [['regression: trailing zeros', [1, 2, 1, 0], {'type': 1, 'group_delay': '1'}], ['regression: interior zero symmetric', [1, 0, 1], {'type': 1, 'group_delay': '1'}], ['repair check: type IV longer', [2, 1, -1, -2], {'type': 4, 'group_delay': '3/2'}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}], ['control: random linear phase 7', [0, 0, 0, 0, 0], 'degenerate'], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}]], [['regression: single tap', [5], {'type': 1, 'group_delay': '0'}], ['regression: padded interior zeros', [0, 2, 0, 0, 2], {'type': 2, 'group_delay': '5/2'}], ['repair check: random linear phase 1', [0, 2, -2, 0, 0, 0], {'type': 4, 'group_delay': '3/2'}], ['control: all zero', [0, 0, 0], 'degenerate'], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}]], [['regression: random linear phase 5', [0, 0, -3, -3, -2, -3, -3, 0], {'type': 1, 'group_delay': '4'}], ['regression: random linear phase 9', [0, 0, -1, -3, 3, -1, 3, -3, -1, 0, 0], {'type': 1, 'group_delay': '5'}], ['repair check: random linear phase 10', [0, 0, 0, -1, 1, 0], {'type': 4, 'group_delay': '7/2'}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}], ['control: random linear phase 7', [0, 0, 0, 0, 0], 'degenerate'], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}], ['control: all zero', [0, 0, 0], 'degenerate']], [['regression: random linear phase 15', [0, 0, 1, -1, -1, 1, 0, 0], {'type': 2, 'group_delay': '7/2'}], ['regression: random linear phase 17', [0, -3, 1, 3, -1, 3, 1, -3], {'type': 1, 'group_delay': '4'}], ['repair check: random linear phase 12', [-1, 1, -1, 1, 0, 0], {'type': 4, 'group_delay': '3/2'}], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: type I | {'group_delay': '1', 'type': 1} | {'group_delay': '1', 'type': 1} | Passed |
| regression: type II | {'group_delay': '1/2', 'type': 2} | {'group_delay': '1/2', 'type': 2} | Passed |
| repair check: type III zero centre | {'group_delay': '1', 'type': 4} | {'group_delay': '1', 'type': 3} | Failed |
| control: type III nonzero centre | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
| control: all zero | degenerate | degenerate | Passed |
| control: not linear phase | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
| control: random linear phase 2 | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
SHA-256 / 84fc97623fc53d4bbad3798d1363a6863fb0af93936c84c5ef125825b2e05c94
3 / The verified repair
Exit 0"""Failure Map reference implementation. Python standard library only."""
import json
from fractions import Fraction
N = 1
observations = []
def solve(x):
h = list(x)
lead = 0
while lead < len(h) and h[lead] == 0:
lead += 1
if lead == len(h):
return 'degenerate'
end = len(h)
while h[end - 1] == 0:
end -= 1
g = h[lead:end]
N = len(g)
sym = all(g[i] == g[N - 1 - i] for i in range(N))
anti = all(g[i] == -g[N - 1 - i] for i in range(N))
if sym:
typ = 1 if N % 2 else 2
elif anti:
typ = 3 if N % 2 else 4
else:
return {'type': None, 'group_delay': None}
return {'type': typ, 'group_delay': str(lead + Fraction(N - 1, 2))}
def check(label, actual, expected):
observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['regression: type I', [1, 2, 1], {'type': 1, 'group_delay': '1'}], ['regression: type II', [1, 1], {'type': 2, 'group_delay': '1/2'}], ['repair check: type III zero centre', [1, 0, -1], {'type': 3, 'group_delay': '1'}], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}], ['control: all zero', [0, 0, 0], 'degenerate'], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}]], [['regression: trailing zeros', [1, 2, 1, 0], {'type': 1, 'group_delay': '1'}], ['regression: interior zero symmetric', [1, 0, 1], {'type': 1, 'group_delay': '1'}], ['repair check: type IV longer', [2, 1, -1, -2], {'type': 4, 'group_delay': '3/2'}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}], ['control: random linear phase 7', [0, 0, 0, 0, 0], 'degenerate'], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}]], [['regression: single tap', [5], {'type': 1, 'group_delay': '0'}], ['regression: padded interior zeros', [0, 2, 0, 0, 2], {'type': 2, 'group_delay': '5/2'}], ['repair check: random linear phase 1', [0, 2, -2, 0, 0, 0], {'type': 4, 'group_delay': '3/2'}], ['control: all zero', [0, 0, 0], 'degenerate'], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}]], [['regression: random linear phase 5', [0, 0, -3, -3, -2, -3, -3, 0], {'type': 1, 'group_delay': '4'}], ['regression: random linear phase 9', [0, 0, -1, -3, 3, -1, 3, -3, -1, 0, 0], {'type': 1, 'group_delay': '5'}], ['repair check: random linear phase 10', [0, 0, 0, -1, 1, 0], {'type': 4, 'group_delay': '7/2'}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}], ['control: random linear phase 7', [0, 0, 0, 0, 0], 'degenerate'], ['control: type III nonzero centre', [1, 2, -1], {'type': None, 'group_delay': None}], ['control: all zero', [0, 0, 0], 'degenerate']], [['regression: random linear phase 15', [0, 0, 1, -1, -1, 1, 0, 0], {'type': 2, 'group_delay': '7/2'}], ['regression: random linear phase 17', [0, -3, 1, 3, -1, 3, 1, -3], {'type': 1, 'group_delay': '4'}], ['repair check: random linear phase 12', [-1, 1, -1, 1, 0, 0], {'type': 4, 'group_delay': '3/2'}], ['control: not linear phase', [1, 2, 3], {'type': None, 'group_delay': None}], ['control: random linear phase 2', [0, 0, 2, 0, 2, 0, -2, 0, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 4', [0, 1, -1, -1, 0], {'type': None, 'group_delay': None}], ['control: random linear phase 6', [0, 3, 2, -3], {'type': None, 'group_delay': None}]]]
for label, args, expected in fixtures[N-1]:
check(label, solve(args), expected)
print(json.dumps({"observations": observations, "passed": all(x["passed"] for x in observations)}, ensure_ascii=False))
raise SystemExit(0 if all(x["passed"] for x in observations) else 1)
| Boundary fixture | Actual | Expected | Outcome |
|---|---|---|---|
| regression: type I | {'group_delay': '1', 'type': 1} | {'group_delay': '1', 'type': 1} | Passed |
| regression: type II | {'group_delay': '1/2', 'type': 2} | {'group_delay': '1/2', 'type': 2} | Passed |
| repair check: type III zero centre | {'group_delay': '1', 'type': 3} | {'group_delay': '1', 'type': 3} | Passed |
| control: type III nonzero centre | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
| control: all zero | degenerate | degenerate | Passed |
| control: not linear phase | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
| control: random linear phase 2 | {'group_delay': None, 'type': None} | {'group_delay': None, 'type': None} | Passed |
SHA-256 / ce6d46c32194e189bff891ddf2e06bbf1f8f7aacd21528f1161ed6c3106c8174
Verification & scope
A deterministic bounded teaching model with a stipulated toy contract; exact rational arithmetic or fixed-decimal rounding keeps outputs strict JSON. It is not a production DSP library and claims no standards conformance. This reproducer isolates one failure mechanism. Results cover the supplied fixtures. Variants within a family share a test contract and should remain grouped when constructing evaluation splits. Related mechanisms with a shared evaluation_group must also remain together; these controlled models are not independent production incidents.
Observations recorded using Python 3.12.14 at 2026-09-29T14:51:38.102673+00:00.
Case digest / 21ead738058a485444eb291cf2faf8bbc11136970b45075e83dc343be3da0178