FAILURE MAP
← Case archive

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

Five-limit just ratio for a semitone interval: integer ratios rendered without denominator · case 01

The octave is returned as "2" and the double octave as "4" instead of "2/1" and "4/1".

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

ROOT CAUSE

The Fraction default string form drops the denominator of whole-number ratios.

VERIFIED REPAIR

Restore the ratio rendering step so that it reads `str(r.numerator) + '/' + str(r.denominator)`.

Unsuccessful approach: Appending "/1" only above unity still renders the unison as "1".

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 = abs(x)
    r = Fraction(table[n % 12]) * 2 ** (n // 12)
    if x < 0:
        r = 1 / r
    return str(r)
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'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (19, '3/1')], [(0, '1/1'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (7, '3/2'), (8, '8/5'), (12, '2/1'), (24, '4/1')], [(0, '1/1'), (7, '3/2'), (8, '8/5'), (9, '5/3'), (10, '9/5'), (11, '15/8'), (19, '3/1'), (36, '8/1')], [(0, '1/1'), (10, '9/5'), (11, '15/8'), (13, '32/15'), (24, '4/1'), (-1, '15/16'), (-2, '8/9'), (-3, '5/6')], [(0, '1/1'), (12, '2/1'), (-1, '15/16'), (-2, '8/9'), (-3, '5/6'), (-5, '3/4'), (-6, '32/45'), (36, '8/1')]]
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 011/1Failed
oracle 116/1516/15Passed
oracle 29/89/8Passed
oracle 36/56/5Passed
oracle 45/45/4Passed
oracle 54/34/3Passed
oracle 645/3245/32Passed
oracle 733/1Failed

SHA-256 / 4c470e6d178b520bb4b4bdd232d93a14a64c61b499624d79d770982aca671ef1

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 / r
    return str(r) + ('/1' if r.denominator == 1 and r > 1 else '')
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'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (19, '3/1')], [(0, '1/1'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (7, '3/2'), (8, '8/5'), (12, '2/1'), (24, '4/1')], [(0, '1/1'), (7, '3/2'), (8, '8/5'), (9, '5/3'), (10, '9/5'), (11, '15/8'), (19, '3/1'), (36, '8/1')], [(0, '1/1'), (10, '9/5'), (11, '15/8'), (13, '32/15'), (24, '4/1'), (-1, '15/16'), (-2, '8/9'), (-3, '5/6')], [(0, '1/1'), (12, '2/1'), (-1, '15/16'), (-2, '8/9'), (-3, '5/6'), (-5, '3/4'), (-6, '32/45'), (36, '8/1')]]
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 011/1Failed
oracle 116/1516/15Passed
oracle 29/89/8Passed
oracle 36/56/5Passed
oracle 45/45/4Passed
oracle 54/34/3Passed
oracle 645/3245/32Passed
oracle 73/13/1Passed

SHA-256 / 4d3a8581eb4d0ed718f4af6ba35837113f3d90cf4fedd62c718657cffaded275

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'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (19, '3/1')], [(0, '1/1'), (4, '5/4'), (5, '4/3'), (6, '45/32'), (7, '3/2'), (8, '8/5'), (12, '2/1'), (24, '4/1')], [(0, '1/1'), (7, '3/2'), (8, '8/5'), (9, '5/3'), (10, '9/5'), (11, '15/8'), (19, '3/1'), (36, '8/1')], [(0, '1/1'), (10, '9/5'), (11, '15/8'), (13, '32/15'), (24, '4/1'), (-1, '15/16'), (-2, '8/9'), (-3, '5/6')], [(0, '1/1'), (12, '2/1'), (-1, '15/16'), (-2, '8/9'), (-3, '5/6'), (-5, '3/4'), (-6, '32/45'), (36, '8/1')]]
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 45/45/4Passed
oracle 54/34/3Passed
oracle 645/3245/32Passed
oracle 73/13/1Passed

SHA-256 / f51a645ca58b0e8ed86eb3a79d0da84481414eb74f9d7d2e771edb0074e5e16a

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.892852+00:00.

Case digest / e3321382b54b5cc2ff1cbee106de89f990c78eed0683556748abbd67ed4cf481