ADR-0131 Benchmark 1 substrate — the primary discriminator for the
mathematics_logic expert promotion under the architecture-aligned
benchmark composite proposed in ADR-0131.
WHAT LANDED:
generate/math_symbolic_normalizer.py
Deterministic univariate polynomial normalizer. Scope: single
variable, integer coefficients, +/-/*/** operators, parens, no
division, no transcendentals. Pipeline: tokenize -> recursive-
descent parse -> expand-and-collect -> canonical string. Refusal
is first-class via SymbolicError; out-of-scope inputs refuse
rather than guess (preserves wrong == 0).
generate/math_symbolic_equivalence.py
check_equivalence(a, b) -> EquivalenceVerdict
Returns EQUIVALENT / NOT_EQUIVALENT / REFUSED with canonical
strings + reason. Compares byte-equal canonical forms.
evals/math_symbolic_equivalence/v1/
cases.jsonl — 30 hand-curated cases across 18 algebraic
identity categories + 2 out-of-scope refusals.
Coverage: commutative, distributive, square +
cube of binomial, difference of squares, FOIL,
collect like terms, zero cancellation, factoring,
exponent combination, unary negation.
runner.py — CLI entry point. Loads cases, builds report,
writes JSON, exits 0/1 on gate pass/fail.
README.md — methodology, scope, dataset categorization,
exit criterion, baseline result.
tests/
test_math_symbolic_normalizer.py — 44 tests covering parser,
algebra primitives,
canonical-form invariants,
and every refusal path.
test_math_symbolic_equivalence.py — 16 tests on the public
check_equivalence API.
test_adr_0131_1_symbolic_equivalence_lane.py
— 8 tests gating the lane:
dataset integrity, exit
criterion, wrong == 0,
determinism (byte-equal
report across runs).
EMPIRICAL RESULT (the lane PASSED):
correct = 30 / 30 (100.0%)
wrong = 0 / 30 (wrong == 0 invariant satisfied)
refused = 0 / 30 (refusals all matched expected)
correct_rate = 1.00
exit_criterion: PASSED (>= 0.95 required)
CONTRAST WITH ADR-0127-0128 GSM8K TRAIN-SAMPLE RESULT (0/0/50):
This is the first benchmark on the mathematics_logic lane where
the architecture's structural strengths fully express. The result
is the empirical inverse of the GSM8K result — and that's
exactly the architecture-benchmark fit ADR-0131 was written to
re-target toward.
REGRESSION: 1033/1033 existing tests green across math + ADR-0126
+ pack ratification + runner. Zero regressions.
SCOPE DISCIPLINE (per ADR-0131.1 v1 plan):
v1 deliberately narrow (univariate, integer, polynomial). Future
ADR-0131.1.B expansions documented in README: multi-variable,
rationals, larger dataset (~500), sealed holdout per ADR-0119.7
pattern.
PARALLEL WORK (per ADR-0131 plan to run all 3 sub-phases concurrently):
- ADR-0131.2: CORE-native teaching-corpus eval (separate PR)
- ADR-0131.3: bounded-grammar word-problem set (separate PR)
These are independent of ADR-0131.1; no shared files, no
cross-PR coordination required beyond final composite gate.
|
||
|---|---|---|
| .. | ||
| __init__.py | ||
| cases.jsonl | ||
| README.md | ||
| report.json | ||
| runner.py | ||
Symbolic Equivalence Benchmark v1 (ADR-0131.1)
The primary discriminator for the mathematics_logic expert
promotion under ADR-0131. Tests whether the engine can determine
that two algebraic expressions are equivalent under deterministic
polynomial normalization.
Scope (v1, intentionally narrow)
- Single variable (
xby default). - Integer coefficients only.
- Operators:
+,-,*,**/^(positive integer exponents). - Parentheses for grouping.
- No division (other than trivial).
- No transcendental functions, no multi-variable, no rationals.
The narrowness is by design. The architecture's strength is exact recall + replay determinism; the benchmark stays inside that envelope so the result is a clean measure of that strength, not a proxy for it.
Pipeline
expression_a -> normalize -> canonical_string_a
expression_b -> normalize -> canonical_string_b
verdict = (canonical_string_a == canonical_string_b)
? EQUIVALENT : NOT_EQUIVALENT
or REFUSED if either expression is out-of-scope
normalize is generate/math_symbolic_normalizer.py:
recursive-descent parser → polynomial expand-and-collect →
canonical string serialization. check_equivalence is
generate/math_symbolic_equivalence.py.
Dataset
cases.jsonl ships 30 hand-curated cases covering:
| Category | Count | Examples |
|---|---|---|
| commutative_add / commutative_mul | 2 | x+1 ≡ 1+x, 3*x ≡ x*3 |
| distributive | 2 | 2*(x+3) ≡ 2*x+6 |
| square_of_binomial | 3 | (x+1)^2 ≡ x^2+2*x+1 |
| difference_of_squares | 2 | (x+1)*(x-1) ≡ x^2-1 |
| cube_of_binomial | 2 | (x+1)^3 ≡ x^3+3*x^2+3*x+1 |
| foil | 1 | (x+2)*(x+3) ≡ x^2+5*x+6 |
| collect_like_terms | 2 | 2*x+3*x ≡ 5*x |
| zero_cancellation | 1 | x-x ≡ 0 |
| repeated_addition | 1 | x+x+x+x ≡ 4*x |
| exponent_combine | 1 | x^2*x ≡ x^3 |
| product_of_factors | 1 | x*(x+1)*(x-1) ≡ x^3-x |
| unary_neg_distribute | 1 | -(x+1) ≡ -x-1 |
| distributive_collect | 1 | 3*(x+1)+2*(x-1) ≡ 5*x+1 |
| different_constant / coefficient / degree | 3 | x+1 ≢ x+2 |
| sign_flipped | 2 | (x+1)^2 ≢ (x-1)^2 |
| distributive_miss / foil_miss / cube_miss | 3 | 2*(x+3) ≢ 2*x+3 |
| out_of_scope_variable | 1 | x+y → REFUSED |
| out_of_scope_division | 1 | x/2 → REFUSED |
20 expected-equivalent + 8 expected-not-equivalent + 2 expected-refused.
Exit criterion (per ADR-0131 Benchmark 1)
correct_rate >= 0.95
wrong == 0
wrong is incremented only when the engine produces a definite
answer that disagrees with the expected verdict. Refusal on an
out-of-scope case is correct when expected; refused when
unexpected (which the lane test flags as a normalizer-coverage
regression).
Running the lane
python -m evals.math_symbolic_equivalence.v1.runner
# exits 0 if exit criterion passes, 1 otherwise
# writes report.json with counts + per-case verdicts
v1 result (baseline at landing)
correct = 30 / 30 (100.0%)
wrong = 0 / 30 (wrong == 0 invariant satisfied)
refused = 0 / 30 (both expected-refused cases were caught correctly)
exit: PASSED
This is the first benchmark on the mathematics_logic lane where
the architecture's structural strengths fully express. The result
is not a claim about how hard the cases are; it's a claim about
the architecture-benchmark fit being correct.
Future expansion (ADR-0131.1.B and beyond)
- Multi-variable polynomials (
x,y,zsimultaneous). - Rational coefficients (Fraction).
- Larger dataset (~500 cases per ADR-0131's Benchmark 1 spec).
- Sealed holdout (mirror ADR-0119.7's pyrage X25519 pattern).
- More algebraic identities (Pascal triangle expansions, factoring, partial fractions for rationals).
v1 ships the minimum viable substrate. The exit criterion is met; the dataset can grow without breaking the contract.