FAILURE MAP
← Case archive

FA-81086 / Music interval and transposition theory / Open access

Five-limit just ratio for a semitone interval: descending intervals looked up by floor modulo · case 01

A descending whole tone returns 9/10 instead of 8/9 and a descending tritone 45/64 instead of 32/45.

Verified by executionVariant 1 · 8 checks per implementationDownload source bundle ↓JSON ↗

ROOT CAUSE

Descending sizes are mapped through Python floor modulo into the ascending table, which is not the reciprocal for asymmetric entries.

VERIFIED REPAIR

Restore the descending reciprocal step so that it reads `n = abs(x) r = Fraction(table[n % 12]) * 2 ** (n // 12) if x < 0: r = 1 / r`.

Unsuccessful approach: Taking the reciprocal of the table entry alone drops the octave factor for descending compound intervals.

Case contract

Input an integer semitone count (negative = descending). Ascending ratios use the table 1/1 16/15 9/8 6/5 5/4 4/3 45/32 3/2 8/5 5/3 9/5 15/8 per pitch class, times 2 per octave. A descending interval is the reciprocal of the ascending one of the same size. Return "p/q" in lowest terms (always with a denominator); non-integers and booleans return None.

Why this case matters

Tuning tables and retuning tools convert interval sizes to exact frequency ratios.

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):
    table = ['1/1', '16/15', '9/8', '6/5', '5/4', '4/3', '45/32', '3/2', '8/5', '5/3', '9/5', '15/8']
    if not isinstance(x, int) or isinstance(x, bool):
        return None
    n = x
    r = Fraction(table[n % 12]) * Fraction(2) ** (n // 12)
    return str(r.numerator) + '/' + str(r.denominator)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(0, '1/1'), (1, '16/15'), (2, '9/8'), (3, '6/5'), (-2, '8/9'), (-12, '1/2'), (-14, '4/9'), (-19, '1/3')], [(3, '6/5'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (-6, '32/45'), (-13, '15/32'), (-24, '1/4'), (-10, '5/9')], [(6, '45/32'), (7, '3/2'), (8, '8/5'), (9, '5/3'), (10, '9/5'), (-2, '8/9'), (-12, '1/2'), (-14, '4/9')], [(9, '5/3'), (10, '9/5'), (11, '15/8'), (12, '2/1'), (-6, '32/45'), (-13, '15/32'), (-19, '1/3'), (-10, '5/9')], [(12, '2/1'), (13, '32/15'), (19, '3/1'), (24, '4/1'), (-1, '15/16'), (-2, '8/9'), (-14, '4/9'), (-24, '1/4')]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("oracle %d" % i, 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 fixtureActualExpectedOutcome
oracle 01/11/1Passed
oracle 116/1516/15Passed
oracle 29/89/8Passed
oracle 36/56/5Passed
oracle 49/108/9Failed
oracle 51/21/2Passed
oracle 69/204/9Failed
oracle 71/31/3Passed

SHA-256 / a47ea4fa218fe39463c8028a7eaedbf3db848a46ddbf6c9ae9fd7b295f0926b7

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):
    table = ['1/1', '16/15', '9/8', '6/5', '5/4', '4/3', '45/32', '3/2', '8/5', '5/3', '9/5', '15/8']
    if not isinstance(x, int) or isinstance(x, bool):
        return None
    n = abs(x)
    r = Fraction(table[n % 12]) * 2 ** (n // 12)
    if x < 0:
        r = 1 / Fraction(table[n % 12])
    return str(r.numerator) + '/' + str(r.denominator)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(0, '1/1'), (1, '16/15'), (2, '9/8'), (3, '6/5'), (-2, '8/9'), (-12, '1/2'), (-14, '4/9'), (-19, '1/3')], [(3, '6/5'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (-6, '32/45'), (-13, '15/32'), (-24, '1/4'), (-10, '5/9')], [(6, '45/32'), (7, '3/2'), (8, '8/5'), (9, '5/3'), (10, '9/5'), (-2, '8/9'), (-12, '1/2'), (-14, '4/9')], [(9, '5/3'), (10, '9/5'), (11, '15/8'), (12, '2/1'), (-6, '32/45'), (-13, '15/32'), (-19, '1/3'), (-10, '5/9')], [(12, '2/1'), (13, '32/15'), (19, '3/1'), (24, '4/1'), (-1, '15/16'), (-2, '8/9'), (-14, '4/9'), (-24, '1/4')]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("oracle %d" % i, 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 fixtureActualExpectedOutcome
oracle 01/11/1Passed
oracle 116/1516/15Passed
oracle 29/89/8Passed
oracle 36/56/5Passed
oracle 48/98/9Passed
oracle 51/11/2Failed
oracle 68/94/9Failed
oracle 72/31/3Failed

SHA-256 / 21bf52a05f8b9b4cbf1b13a2e01d82600bdb2d2c0c5634dc77196c89b7693ba3

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):
    table = ['1/1', '16/15', '9/8', '6/5', '5/4', '4/3', '45/32', '3/2', '8/5', '5/3', '9/5', '15/8']
    if not isinstance(x, int) or isinstance(x, bool):
        return None
    n = abs(x)
    r = Fraction(table[n % 12]) * 2 ** (n // 12)
    if x < 0:
        r = 1 / r
    return str(r.numerator) + '/' + str(r.denominator)
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[(0, '1/1'), (1, '16/15'), (2, '9/8'), (3, '6/5'), (-2, '8/9'), (-12, '1/2'), (-14, '4/9'), (-19, '1/3')], [(3, '6/5'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (-6, '32/45'), (-13, '15/32'), (-24, '1/4'), (-10, '5/9')], [(6, '45/32'), (7, '3/2'), (8, '8/5'), (9, '5/3'), (10, '9/5'), (-2, '8/9'), (-12, '1/2'), (-14, '4/9')], [(9, '5/3'), (10, '9/5'), (11, '15/8'), (12, '2/1'), (-6, '32/45'), (-13, '15/32'), (-19, '1/3'), (-10, '5/9')], [(12, '2/1'), (13, '32/15'), (19, '3/1'), (24, '4/1'), (-1, '15/16'), (-2, '8/9'), (-14, '4/9'), (-24, '1/4')]]
for i, (args, expected) in enumerate(fixtures[N-1]):
    check("oracle %d" % i, 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 fixtureActualExpectedOutcome
oracle 01/11/1Passed
oracle 116/1516/15Passed
oracle 29/89/8Passed
oracle 36/56/5Passed
oracle 48/98/9Passed
oracle 51/21/2Passed
oracle 64/94/9Passed
oracle 71/31/3Passed

SHA-256 / d1a89f2d37641f1220eb803a30814911336d2d1e6d73dfefb90eefc1345e4d55

Verification & scope

A deterministic bounded teaching model with a stipulated toy contract; it is not a complete music notation or theory engine. 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:49:59.884644+00:00.

Case digest / 4e8a5e6c0db4ed4b22623eb92eb65af73c7fff722940130398504ada6fc42f30