FAILURE MAP
← Case archive

FA-12451 / Molecular graph representation / Open access

Dative donor and acceptor swap during canonicalization · case 01

Dative donor and acceptor swap during canonicalization.

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

ROOT CAUSE

Sorting every bond destroys directed donor-to-acceptor semantics.

VERIFIED REPAIR

Implement the explicit toy representation contract: Return [kind,a,b]; kind dative preserves donor a and acceptor b, kind covalent sorts numeric endpoint IDs.

Unsuccessful approach: Preserving all endpoint order prevents undirected covalent canonicalization.

Case contract

Return [kind,a,b]; kind dative preserves donor a and acceptor b, kind covalent sorts numeric endpoint IDs.

Why this case matters

Controlled molecular graph interchange model; tests isolate atom or bond representation errors without claiming chemical validity or production toolkit equivalence.

1 / The failure

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(kind, a, b):
    return [kind,min(a,b),max(a,b)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('reverse dative', solve('dative', N+2,N), ['dative',N+2,N])
check('forward dative', solve('dative',N,N+2), ['dative',N,N+2])
check('reverse covalent', solve('covalent',N+2,N), ['covalent',N,N+2])
check('forward covalent', solve('covalent',N,N+2), ['covalent',N,N+2])
check('zero donor', solve('dative',0,N), ['dative',0,N])
check('zero covalent endpoint', solve('covalent',N,0), ['covalent',0,N])
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
reverse dative['dative', 1, 3]['dative', 3, 1]Failed
forward dative['dative', 1, 3]['dative', 1, 3]Passed
reverse covalent['covalent', 1, 3]['covalent', 1, 3]Passed
forward covalent['covalent', 1, 3]['covalent', 1, 3]Passed
zero donor['dative', 0, 1]['dative', 0, 1]Passed
zero covalent endpoint['covalent', 0, 1]['covalent', 0, 1]Passed

SHA-256 / baac9aa1cd624eddf3073f7656d0e6e79bd29cdf0f505030f2dda0320f6c958e

2 / The unsuccessful fix

Exit 1
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(kind, a, b):
    return [kind,a,b]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('reverse dative', solve('dative', N+2,N), ['dative',N+2,N])
check('forward dative', solve('dative',N,N+2), ['dative',N,N+2])
check('reverse covalent', solve('covalent',N+2,N), ['covalent',N,N+2])
check('forward covalent', solve('covalent',N,N+2), ['covalent',N,N+2])
check('zero donor', solve('dative',0,N), ['dative',0,N])
check('zero covalent endpoint', solve('covalent',N,0), ['covalent',0,N])
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
reverse dative['dative', 3, 1]['dative', 3, 1]Passed
forward dative['dative', 1, 3]['dative', 1, 3]Passed
reverse covalent['covalent', 3, 1]['covalent', 1, 3]Failed
forward covalent['covalent', 1, 3]['covalent', 1, 3]Passed
zero donor['dative', 0, 1]['dative', 0, 1]Passed
zero covalent endpoint['covalent', 1, 0]['covalent', 0, 1]Failed

SHA-256 / da23db69789fa7287101814a28afa3b6dc43d0bfa2f88bcb27ba0c2c789a82cd

3 / The verified repair

Exit 0
"""Failure Map reference implementation. Python standard library only."""
import json

N = 1
observations = []
def solve(kind, a, b):
    return [kind,a,b] if kind == "dative" else [kind,min(a,b),max(a,b)]
def check(label, actual, expected):
    observations.append({"check": label, "actual": actual, "expected": expected, "passed": actual == expected})
check('reverse dative', solve('dative', N+2,N), ['dative',N+2,N])
check('forward dative', solve('dative',N,N+2), ['dative',N,N+2])
check('reverse covalent', solve('covalent',N+2,N), ['covalent',N,N+2])
check('forward covalent', solve('covalent',N,N+2), ['covalent',N,N+2])
check('zero donor', solve('dative',0,N), ['dative',0,N])
check('zero covalent endpoint', solve('covalent',N,0), ['covalent',0,N])
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
reverse dative['dative', 3, 1]['dative', 3, 1]Passed
forward dative['dative', 1, 3]['dative', 1, 3]Passed
reverse covalent['covalent', 1, 3]['covalent', 1, 3]Passed
forward covalent['covalent', 1, 3]['covalent', 1, 3]Passed
zero donor['dative', 0, 1]['dative', 0, 1]Passed
zero covalent endpoint['covalent', 0, 1]['covalent', 0, 1]Passed

SHA-256 / 395fd27856957223a4695bab2cc27c013004c6b6ebaaa31e046d0cd1af569fbd

Verification & scope

Toy representation only; no valence inference, chemical sanitization, synthesis, or real molecular identity determination. 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:38:56.891864+00:00.

Case digest / 244adf728e6d4c68d566877ace2688821561ee776a1897b8a9469a154ff790de