FAILURE MAP
← Case archive

FA-79856 / Typography line breaking / Open access

Glue-set badness rating: badness rounding stage · case 01

Badness of lines with fractional ratios drifts by several points.

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

ROOT CAUSE

The ratio is rounded to one decimal before it is cubed, rounding at the wrong stage.

THE FAILURE

The ratio is rounded to one decimal before it is cubed, rounding at the wrong stage.

Unsuccessful approach: Using Python's round on the scaled value applies banker's rounding and drops 12.5 to 12.

Case contract

Input [natural, stretch, shrink, width, tolerance] (ints). shortfall=width-natural. Positive shortfall with zero stretch is underfull 10000 very_loose; shrinking past total shrink is overfull 1000000 tight. r=shortfall/stretch (or /shrink when negative); badness=min(10000, floor(100*|r|^3+1/2)); fitness tight r<-1/2, decent r<=1/2, loose r<=1, else very_loose; status ok iff badness<=tolerance. Return [status, badness, fitness].

Why this case matters

Line breaking decides where paragraphs wrap on screen and in print; a wrong decision point shifts every following line.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    natural, stretch, shrink, width, tolerance = x
    shortfall = width - natural
    if shortfall > 0:
        if stretch == 0:
            return ['underfull', 10000, 'very_loose']
        r = Fraction(shortfall, stretch)
    elif shortfall < 0:
        if -shortfall > shrink:
            return ['overfull', 1000000, 'tight']
        r = Fraction(shortfall, shrink)
    else:
        r = Fraction(0)
    badness = min(10000, math.floor(100 * round(abs(r), 1) ** 3 + Fraction(1, 2)))
    if r < Fraction(-1, 2):
        fitness = 'tight'
    elif r <= Fraction(1, 2):
        fitness = 'decent'
    elif r <= 1:
        fitness = 'loose'
    else:
        fitness = 'very_loose'
    status = 'ok' if badness <= tolerance else 'underfull'
    return [status, badness, fitness]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: badness rounding stage', [84, 20, 2, 101, 500], ['ok', 61, 'loose']), ('regression: badness rounding stage', [82, 6, 5, 98, 200], ['underfull', 1896, 'very_loose']), ('half stretch ratio rounds 12.5 up', [100, 10, 5, 105, 200], ['ok', 13, 'decent']), ('partial-repair probe', [111, 8, 7, 131, 150], ['underfull', 1563, 'very_loose']), ('very loose over tolerance', [100, 4, 0, 110, 200], ['underfull', 1563, 'very_loose']), ('exact natural width', [100, 10, 5, 100, 200], ['ok', 0, 'decent']), ('control layout', [83, 0, 3, 97, 100], ['underfull', 10000, 'very_loose']), ('control layout', [94, 20, 0, 108, 100], ['ok', 34, 'loose'])], [('regression: badness rounding stage', [102, 16, 2, 113, 150], ['ok', 32, 'loose']), ('regression: badness rounding stage', [64, 8, 7, 77, 500], ['ok', 429, 'very_loose']), ('partial-repair probe', [88, 8, 8, 84, 150], ['ok', 13, 'decent']), ('partial-repair probe', [117, 2, 12, 111, 100], ['ok', 13, 'decent']), ('very loose over tolerance', [100, 4, 0, 110, 200], ['underfull', 1563, 'very_loose']), ('full shrink is still acceptable', [100, 10, 5, 95, 200], ['ok', 100, 'tight']), ('control layout', [106, 16, 11, 95, 200], ['ok', 100, 'tight']), ('control layout', [80, 1, 6, 84, 1000], ['underfull', 6400, 'very_loose'])], [('regression: badness rounding stage', [89, 4, 12, 80, 150], ['ok', 42, 'tight']), ('regression: badness rounding stage', [119, 4, 10, 134, 100], ['underfull', 5273, 'very_loose']), ('partial-repair probe', [120, 12, 3, 126, 1000], ['ok', 13, 'decent']), ('partial-repair probe', [86, 6, 3, 89, 200], ['ok', 13, 'decent']), ('exact natural width', [100, 10, 5, 100, 200], ['ok', 0, 'decent']), ('full shrink is still acceptable', [100, 10, 5, 95, 200], ['ok', 100, 'tight']), ('control layout', [66, 4, 5, 60, 200], ['overfull', 1000000, 'tight']), ('control layout', [94, 20, 0, 108, 100], ['ok', 34, 'loose'])], [('regression: badness rounding stage', [88, 3, 12, 79, 1000], ['ok', 42, 'tight']), ('regression: badness rounding stage', [107, 16, 10, 111, 1000], ['ok', 2, 'decent']), ('partial-repair probe', [66, 2, 3, 75, 150], ['underfull', 9113, 'very_loose']), ('partial-repair probe', [120, 12, 3, 126, 1000], ['ok', 13, 'decent']), ('rigid line with slack', [100, 0, 5, 110, 200], ['underfull', 10000, 'very_loose']), ('very loose over tolerance', [100, 4, 0, 110, 200], ['underfull', 1563, 'very_loose']), ('control layout', [64, 0, 3, 50, 1000], ['overfull', 1000000, 'tight']), ('control layout', [64, 4, 9, 52, 100], ['overfull', 1000000, 'tight'])], [('regression: badness rounding stage', [80, 12, 5, 88, 500], ['ok', 30, 'loose']), ('regression: badness rounding stage', [65, 16, 4, 69, 1000], ['ok', 2, 'decent']), ('partial-repair probe', [117, 2, 12, 111, 100], ['ok', 13, 'decent']), ('partial-repair probe', [109, 8, 11, 129, 100], ['underfull', 1563, 'very_loose']), ('badness cap at 10000', [100, 2, 0, 150, 200], ['underfull', 10000, 'very_loose']), ('exact natural width', [100, 10, 5, 100, 200], ['ok', 0, 'decent']), ('control layout', [81, 4, 5, 72, 100], ['overfull', 1000000, 'tight']), ('control layout', [76, 20, 1, 72, 200], ['overfull', 1000000, 'tight'])]]
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 fixtureActualExpectedOutcome
regression: badness rounding stage['ok', 51, 'loose']['ok', 61, 'loose']Failed
regression: badness rounding stage['underfull', 1968, 'very_loose']['underfull', 1896, 'very_loose']Failed
half stretch ratio rounds 12.5 up['ok', 13, 'decent']['ok', 13, 'decent']Passed
partial-repair probe['underfull', 1563, 'very_loose']['underfull', 1563, 'very_loose']Passed
very loose over tolerance['underfull', 1563, 'very_loose']['underfull', 1563, 'very_loose']Passed
exact natural width['ok', 0, 'decent']['ok', 0, 'decent']Passed
control layout['underfull', 10000, 'very_loose']['underfull', 10000, 'very_loose']Passed
control layout['ok', 34, 'loose']['ok', 34, 'loose']Passed

SHA-256 / c4954c9dacdb85940c9e81532eff6c26cf99ebc8b8b1a2610d19ba45ae9cce04

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(x):
    natural, stretch, shrink, width, tolerance = x
    shortfall = width - natural
    if shortfall > 0:
        if stretch == 0:
            return ['underfull', 10000, 'very_loose']
        r = Fraction(shortfall, stretch)
    elif shortfall < 0:
        if -shortfall > shrink:
            return ['overfull', 1000000, 'tight']
        r = Fraction(shortfall, shrink)
    else:
        r = Fraction(0)
    badness = min(10000, round(100 * abs(r) ** 3))
    if r < Fraction(-1, 2):
        fitness = 'tight'
    elif r <= Fraction(1, 2):
        fitness = 'decent'
    elif r <= 1:
        fitness = 'loose'
    else:
        fitness = 'very_loose'
    status = 'ok' if badness <= tolerance else 'underfull'
    return [status, badness, fitness]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[('regression: badness rounding stage', [84, 20, 2, 101, 500], ['ok', 61, 'loose']), ('regression: badness rounding stage', [82, 6, 5, 98, 200], ['underfull', 1896, 'very_loose']), ('half stretch ratio rounds 12.5 up', [100, 10, 5, 105, 200], ['ok', 13, 'decent']), ('partial-repair probe', [111, 8, 7, 131, 150], ['underfull', 1563, 'very_loose']), ('very loose over tolerance', [100, 4, 0, 110, 200], ['underfull', 1563, 'very_loose']), ('exact natural width', [100, 10, 5, 100, 200], ['ok', 0, 'decent']), ('control layout', [83, 0, 3, 97, 100], ['underfull', 10000, 'very_loose']), ('control layout', [94, 20, 0, 108, 100], ['ok', 34, 'loose'])], [('regression: badness rounding stage', [102, 16, 2, 113, 150], ['ok', 32, 'loose']), ('regression: badness rounding stage', [64, 8, 7, 77, 500], ['ok', 429, 'very_loose']), ('partial-repair probe', [88, 8, 8, 84, 150], ['ok', 13, 'decent']), ('partial-repair probe', [117, 2, 12, 111, 100], ['ok', 13, 'decent']), ('very loose over tolerance', [100, 4, 0, 110, 200], ['underfull', 1563, 'very_loose']), ('full shrink is still acceptable', [100, 10, 5, 95, 200], ['ok', 100, 'tight']), ('control layout', [106, 16, 11, 95, 200], ['ok', 100, 'tight']), ('control layout', [80, 1, 6, 84, 1000], ['underfull', 6400, 'very_loose'])], [('regression: badness rounding stage', [89, 4, 12, 80, 150], ['ok', 42, 'tight']), ('regression: badness rounding stage', [119, 4, 10, 134, 100], ['underfull', 5273, 'very_loose']), ('partial-repair probe', [120, 12, 3, 126, 1000], ['ok', 13, 'decent']), ('partial-repair probe', [86, 6, 3, 89, 200], ['ok', 13, 'decent']), ('exact natural width', [100, 10, 5, 100, 200], ['ok', 0, 'decent']), ('full shrink is still acceptable', [100, 10, 5, 95, 200], ['ok', 100, 'tight']), ('control layout', [66, 4, 5, 60, 200], ['overfull', 1000000, 'tight']), ('control layout', [94, 20, 0, 108, 100], ['ok', 34, 'loose'])], [('regression: badness rounding stage', [88, 3, 12, 79, 1000], ['ok', 42, 'tight']), ('regression: badness rounding stage', [107, 16, 10, 111, 1000], ['ok', 2, 'decent']), ('partial-repair probe', [66, 2, 3, 75, 150], ['underfull', 9113, 'very_loose']), ('partial-repair probe', [120, 12, 3, 126, 1000], ['ok', 13, 'decent']), ('rigid line with slack', [100, 0, 5, 110, 200], ['underfull', 10000, 'very_loose']), ('very loose over tolerance', [100, 4, 0, 110, 200], ['underfull', 1563, 'very_loose']), ('control layout', [64, 0, 3, 50, 1000], ['overfull', 1000000, 'tight']), ('control layout', [64, 4, 9, 52, 100], ['overfull', 1000000, 'tight'])], [('regression: badness rounding stage', [80, 12, 5, 88, 500], ['ok', 30, 'loose']), ('regression: badness rounding stage', [65, 16, 4, 69, 1000], ['ok', 2, 'decent']), ('partial-repair probe', [117, 2, 12, 111, 100], ['ok', 13, 'decent']), ('partial-repair probe', [109, 8, 11, 129, 100], ['underfull', 1563, 'very_loose']), ('badness cap at 10000', [100, 2, 0, 150, 200], ['underfull', 10000, 'very_loose']), ('exact natural width', [100, 10, 5, 100, 200], ['ok', 0, 'decent']), ('control layout', [81, 4, 5, 72, 100], ['overfull', 1000000, 'tight']), ('control layout', [76, 20, 1, 72, 200], ['overfull', 1000000, 'tight'])]]
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 fixtureActualExpectedOutcome
regression: badness rounding stage['ok', 61, 'loose']['ok', 61, 'loose']Passed
regression: badness rounding stage['underfull', 1896, 'very_loose']['underfull', 1896, 'very_loose']Passed
half stretch ratio rounds 12.5 up['ok', 12, 'decent']['ok', 13, 'decent']Failed
partial-repair probe['underfull', 1562, 'very_loose']['underfull', 1563, 'very_loose']Failed
very loose over tolerance['underfull', 1562, 'very_loose']['underfull', 1563, 'very_loose']Failed
exact natural width['ok', 0, 'decent']['ok', 0, 'decent']Passed
control layout['underfull', 10000, 'very_loose']['underfull', 10000, 'very_loose']Passed
control layout['ok', 34, 'loose']['ok', 34, 'loose']Passed

SHA-256 / 0abfe0dedd574be2e60619572acbe890d99248c0ab6df48a45c2de602882e794

HELD IN THE MEMBER ARCHIVE

The verified repair and its recorded checks are member-only.

This mechanism has 8 recorded checks per implementation. The open-access tier publishes the failure and the unsuccessful fix; the repaired source that passes every check, and the observations that prove it, are available to members.

Every case sharing this mechanism uses the same contract and the same repair, so this one record is held back for all of them.

Member access is invitation-based. Sign in with your invited account to inspect the repair.

Sign in to the archive ↗

Verification & scope

A deterministic toy typesetting model with integer widths and a stipulated rule set; it does not claim conformance to any 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:48.293310+00:00.

Case digest / d4c4a6fcb8db02978711734c40d4815945eee32f8fa4350002a8d970a21c52ed