FAILURE MAP
← Case archive

FA-97641 / Knitting and sewing pattern grading / Open access

Flat crochet circle planner: radius per round · case 01

A 10 cm coaster is worked to 20 cm.

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

ROOT CAUSE

Each round is assumed to add its height to the diameter rather than the radius.

VERIFIED REPAIR

Divide the diameter by twice the round height and round up.

Unsuccessful approach: Rounding to nearest can stop short of the target diameter.

Case contract

Base stitches per round: sc 6, hdc 8, dc 12 (others -> "error: stitch"). Each round adds one round height to the radius. rounds = ceiling(diameter/(2*height)). Round k has base*k stitches. Return [rounds, stitches in last round, total stitches base*rounds*(rounds+1)/2].

Why this case matters

Amigurumi and rug patterns size flat circles by rounds of evenly spaced increases.

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(stitch, diameter, round_height):
    BASE = {'sc': 6, 'hdc': 8, 'dc': 12}
    if stitch not in BASE:
        return 'error: stitch'
    h = Fraction(round_height)
    rounds = math.ceil(Fraction(diameter) / h)
    b = BASE[stitch]
    return [rounds, b * rounds, b * rounds * (rounds + 1) // 2]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['coaster', ['sc', 10, '0.5'], [10, 60, 330]], ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['regression: radius per round', ['hdc', 12, '2'], [3, 24, 48]],
  ['repair check: radius per round', ['sc', 20, '0.75'], [14, 84, 630]],
  ['generated control 1', ['dc', 10, '1.5'], [4, 48, 120]],
  ['generated control 2', ['hdc', 5, '0.75'], [4, 32, 80]],
  ['generated control 3', ['sc', 10, '1.5'], [4, 24, 60]]],
 [['dc mat', ['dc', 30, '1.5'], [10, 120, 660]], ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['regression: radius per round', ['sc', 12, '0.5'], [12, 72, 468]],
  ['repair check: radius per round', ['sc', 5, '2'], [2, 12, 18]],
  ['generated control 1', ['dc', 12, '2'], [3, 36, 72]],
  ['generated control 2', ['hdc', 15, '1'], [8, 64, 288]],
  ['generated control 3', ['tr', 20, '0.5'], 'error: stitch']],
 [['treble unknown', ['tr', 10, '1'], 'error: stitch'], ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['regression: radius per round', ['dc', 15, '0.5'], [15, 180, 1440]],
  ['repair check: radius per round', ['hdc', 10, '1.5'], [4, 32, 80]],
  ['generated control 1', ['hdc', 12, '0.5'], [12, 96, 624]],
  ['generated control 2', ['hdc', 30, '1'], [15, 120, 960]],
  ['generated control 3', ['sc', 10, '1.5'], [4, 24, 60]]],
 [['coaster', ['sc', 10, '0.5'], [10, 60, 330]], ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['regression: radius per round', ['dc', 10, '0.5'], [10, 120, 660]],
  ['repair check: radius per round', ['hdc', 10, '1.5'], [4, 32, 80]],
  ['generated control 1', ['tr', 5, '2'], 'error: stitch'],
  ['generated control 2', ['hdc', 15, '1.5'], [5, 40, 120]],
  ['generated control 3', ['hdc', 20, '2'], [5, 40, 120]]],
 [['dc mat', ['dc', 30, '1.5'], [10, 120, 660]], ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['regression: radius per round', ['dc', 5, '2'], [2, 24, 36]],
  ['repair check: radius per round', ['hdc', 20, '0.75'], [14, 112, 840]],
  ['generated control 1', ['tr', 30, '2'], 'error: stitch'],
  ['generated control 2', ['tr', 20, '2'], 'error: stitch'],
  ['generated control 3', ['dc', 15, '1'], [8, 96, 432]]]]
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
coaster[20, 120, 1260][10, 60, 330]Failed
dc mat[20, 240, 2520][10, 120, 660]Failed
treble unknownerror: stitcherror: stitchPassed
regression: radius per round[6, 48, 168][3, 24, 48]Failed
repair check: radius per round[27, 162, 2268][14, 84, 630]Failed
generated control 1[7, 84, 336][4, 48, 120]Failed
generated control 2[7, 56, 224][4, 32, 80]Failed
generated control 3[7, 42, 168][4, 24, 60]Failed

SHA-256 / 9e5e228cc1baac064674222860736aa1802ea32ac5d0672bf30c0239813349b5

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(stitch, diameter, round_height):
    BASE = {'sc': 6, 'hdc': 8, 'dc': 12}
    if stitch not in BASE:
        return 'error: stitch'
    h = Fraction(round_height)
    rounds = math.floor(Fraction(diameter) / (2 * h) + Fraction(1, 2))
    b = BASE[stitch]
    return [rounds, b * rounds, b * rounds * (rounds + 1) // 2]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['coaster', ['sc', 10, '0.5'], [10, 60, 330]], ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['regression: radius per round', ['hdc', 12, '2'], [3, 24, 48]],
  ['repair check: radius per round', ['sc', 20, '0.75'], [14, 84, 630]],
  ['generated control 1', ['dc', 10, '1.5'], [4, 48, 120]],
  ['generated control 2', ['hdc', 5, '0.75'], [4, 32, 80]],
  ['generated control 3', ['sc', 10, '1.5'], [4, 24, 60]]],
 [['dc mat', ['dc', 30, '1.5'], [10, 120, 660]], ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['regression: radius per round', ['sc', 12, '0.5'], [12, 72, 468]],
  ['repair check: radius per round', ['sc', 5, '2'], [2, 12, 18]],
  ['generated control 1', ['dc', 12, '2'], [3, 36, 72]],
  ['generated control 2', ['hdc', 15, '1'], [8, 64, 288]],
  ['generated control 3', ['tr', 20, '0.5'], 'error: stitch']],
 [['treble unknown', ['tr', 10, '1'], 'error: stitch'], ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['regression: radius per round', ['dc', 15, '0.5'], [15, 180, 1440]],
  ['repair check: radius per round', ['hdc', 10, '1.5'], [4, 32, 80]],
  ['generated control 1', ['hdc', 12, '0.5'], [12, 96, 624]],
  ['generated control 2', ['hdc', 30, '1'], [15, 120, 960]],
  ['generated control 3', ['sc', 10, '1.5'], [4, 24, 60]]],
 [['coaster', ['sc', 10, '0.5'], [10, 60, 330]], ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['regression: radius per round', ['dc', 10, '0.5'], [10, 120, 660]],
  ['repair check: radius per round', ['hdc', 10, '1.5'], [4, 32, 80]],
  ['generated control 1', ['tr', 5, '2'], 'error: stitch'],
  ['generated control 2', ['hdc', 15, '1.5'], [5, 40, 120]],
  ['generated control 3', ['hdc', 20, '2'], [5, 40, 120]]],
 [['dc mat', ['dc', 30, '1.5'], [10, 120, 660]], ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['regression: radius per round', ['dc', 5, '2'], [2, 24, 36]],
  ['repair check: radius per round', ['hdc', 20, '0.75'], [14, 112, 840]],
  ['generated control 1', ['tr', 30, '2'], 'error: stitch'],
  ['generated control 2', ['tr', 20, '2'], 'error: stitch'],
  ['generated control 3', ['dc', 15, '1'], [8, 96, 432]]]]
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
coaster[10, 60, 330][10, 60, 330]Passed
dc mat[10, 120, 660][10, 120, 660]Passed
treble unknownerror: stitcherror: stitchPassed
regression: radius per round[3, 24, 48][3, 24, 48]Passed
repair check: radius per round[13, 78, 546][14, 84, 630]Failed
generated control 1[3, 36, 72][4, 48, 120]Failed
generated control 2[3, 24, 48][4, 32, 80]Failed
generated control 3[3, 18, 36][4, 24, 60]Failed

SHA-256 / 479c37e138c1e53e87ff14f4d72fafbab8473a2e7d30acee2f71a4e082f1a8e3

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json
import math
from fractions import Fraction
N = 1
observations = []
def solve(stitch, diameter, round_height):
    BASE = {'sc': 6, 'hdc': 8, 'dc': 12}
    if stitch not in BASE:
        return 'error: stitch'
    h = Fraction(round_height)
    rounds = math.ceil(Fraction(diameter) / (2 * h))
    b = BASE[stitch]
    return [rounds, b * rounds, b * rounds * (rounds + 1) // 2]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
fixtures = [[['coaster', ['sc', 10, '0.5'], [10, 60, 330]], ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['regression: radius per round', ['hdc', 12, '2'], [3, 24, 48]],
  ['repair check: radius per round', ['sc', 20, '0.75'], [14, 84, 630]],
  ['generated control 1', ['dc', 10, '1.5'], [4, 48, 120]],
  ['generated control 2', ['hdc', 5, '0.75'], [4, 32, 80]],
  ['generated control 3', ['sc', 10, '1.5'], [4, 24, 60]]],
 [['dc mat', ['dc', 30, '1.5'], [10, 120, 660]], ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['regression: radius per round', ['sc', 12, '0.5'], [12, 72, 468]],
  ['repair check: radius per round', ['sc', 5, '2'], [2, 12, 18]],
  ['generated control 1', ['dc', 12, '2'], [3, 36, 72]],
  ['generated control 2', ['hdc', 15, '1'], [8, 64, 288]],
  ['generated control 3', ['tr', 20, '0.5'], 'error: stitch']],
 [['treble unknown', ['tr', 10, '1'], 'error: stitch'], ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['regression: radius per round', ['dc', 15, '0.5'], [15, 180, 1440]],
  ['repair check: radius per round', ['hdc', 10, '1.5'], [4, 32, 80]],
  ['generated control 1', ['hdc', 12, '0.5'], [12, 96, 624]],
  ['generated control 2', ['hdc', 30, '1'], [15, 120, 960]],
  ['generated control 3', ['sc', 10, '1.5'], [4, 24, 60]]],
 [['coaster', ['sc', 10, '0.5'], [10, 60, 330]], ['dc mat', ['dc', 30, '1.5'], [10, 120, 660]],
  ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['regression: radius per round', ['dc', 10, '0.5'], [10, 120, 660]],
  ['repair check: radius per round', ['hdc', 10, '1.5'], [4, 32, 80]],
  ['generated control 1', ['tr', 5, '2'], 'error: stitch'],
  ['generated control 2', ['hdc', 15, '1.5'], [5, 40, 120]],
  ['generated control 3', ['hdc', 20, '2'], [5, 40, 120]]],
 [['dc mat', ['dc', 30, '1.5'], [10, 120, 660]], ['treble unknown', ['tr', 10, '1'], 'error: stitch'],
  ['coaster', ['sc', 10, '0.5'], [10, 60, 330]],
  ['regression: radius per round', ['dc', 5, '2'], [2, 24, 36]],
  ['repair check: radius per round', ['hdc', 20, '0.75'], [14, 112, 840]],
  ['generated control 1', ['tr', 30, '2'], 'error: stitch'],
  ['generated control 2', ['tr', 20, '2'], 'error: stitch'],
  ['generated control 3', ['dc', 15, '1'], [8, 96, 432]]]]
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
coaster[10, 60, 330][10, 60, 330]Passed
dc mat[10, 120, 660][10, 120, 660]Passed
treble unknownerror: stitcherror: stitchPassed
regression: radius per round[3, 24, 48][3, 24, 48]Passed
repair check: radius per round[14, 84, 630][14, 84, 630]Passed
generated control 1[4, 48, 120][4, 48, 120]Passed
generated control 2[4, 32, 80][4, 32, 80]Passed
generated control 3[4, 24, 60][4, 24, 60]Passed

SHA-256 / 3f383fa5cc369a64e57f55fc5a9c37b8e2c3a6d1b581e9f917d2f9215fa1621a

Verification & scope

A deterministic toy contract stated in full here; it is a bounded teaching model, not an authoritative reference or standards implementation. 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:52:34.148168+00:00.

Case digest / fb0a2a9405dca6171c77f027142beb21d8a24b9327f03a22f92332e0e0d15a9e