FA-12451 / Molecular graph representation / Open access
Dative donor and acceptor swap during canonicalization · case 01
Dative donor and acceptor swap during canonicalization.
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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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 fixture | Actual | Expected | Outcome |
|---|---|---|---|
| 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