--- name: symbolic-check description: "Use SymPy to prove or refute a self-authored algebraic identity, derivative, limit, comparative-static sign, or closed form. Use when exact symbolic manipulation can settle the claim. For parameter sweeps or full theorem proving, use $numerical-check or $lean-check." allowed-tools: - Read - Write - Edit - Bash - AskUserQuestion --- # Symbolic Check: Prove/Refute a Self-Authored Algebra Step with a CAS Verify a symbolic manipulation you wrote — an identity, a derivative, a limit, a comparative-static sign, a closed form — using sympy. Unlike numerical falsification, this can **positively verify** the step: a CAS-confirmed identity *is* correct. ## When to Use - You wrote `A = B`, `∂f/∂x = g`, `lim = L`, `sign(∂f/∂x) = −`, or "the closed form is …" and want it *proven* before it ships. - `symbolic-check`, "verify this algebra / derivative / limit", "check the comparative-static sign", "does this closed form equal the original". - Companion to `mark-unverified` for self-authored algebra (the derivative-sign / closed-form family the rule explicitly names). ## When NOT to Use | Situation | Use instead | |---|---| | A full theorem/lemma you want machine-proven end-to-end | `lean-check` (R3) | | A distributional / probabilistic claim over a parameter space | `numerical-check` (R1) | | Re-verify a computed empirical result | `cross-language-check` | | Conceptual / assumption review | `domain-reviewer` | ## Position in the verification spectrum **R2 — symbolic / CAS.** Can **VERIFY** (prove) or **FALSIFY** a symbolic step; between numerical falsification (R1) and formal proof (R3) in strength. It proves *algebra*, not arbitrary theorems — reasoning beyond symbolic manipulation (measure theory, limits sympy can't evaluate) escalates to `lean-check` or `domain-reviewer`. ## Procedure ### 1. Transcribe the claim precisely, with declared symbol domains - Restate the exact claim: identity `A == B`, derivative `diff(f,x) == g`, limit `limit(f,x,a) == L`, sign `sign(diff(f,x))` over a domain, or closed form `expr == cf`. - **Declare assumptions on the symbols** — `symbols('x', positive=True, real=True)` etc. Comparative-static signs and simplifications are *wrong without the right domain*. State them explicitly (they are part of the claim). ### 2. Prove the core with `.equals()`, not `simplify(...)==0` sympy's `simplify` is heuristic — a **non-zero** result does **not** mean the claim is false, only that simplify gave up. Use `(A - B).equals(0)`, which combines symbolic + random-point numerical testing and returns: - `True` → **VERIFIED** (identity holds) - `False` → **FALSIFIED** (a witness point disproves it) - `None` → **INCONCLUSIVE** (undecided) — go to step 3. For derivatives: `diff(f, x).equals(g)`. For limits: `limit(f, x, a)` and compare to `L`. For a closed form: `expr.equals(cf)`. ### 3. On `None`, escalate — do NOT guess - Try stronger simplifiers targeted at the form: `factor`, `radsimp`, `trigsimp`, `powsimp`, `together`, `rewrite(...)`, `assuming(...)` with the domain. - **Numerically substitute** several random in-domain points into `A - B` — if all ≈ 0, report `INCONCLUSIVE (numerically consistent, symbolically undecided)`; if any is far from 0, that's a **FALSIFIED** witness. - Never upgrade `None` to `VERIFIED`. Undecided is undecided. ### 4. Comparative-static / monotonicity signs - Compute `d = diff(f, x)`. Ask whether `d` has a definite sign *under the assumptions*. - Try `refine(d > 0, Q.positive(...))` / `ask(Q.negative(d), assumptions)`; if sympy can't decide, sample the domain numerically to conjecture the sign, then report `INCONCLUSIVE (sign consistent on N points)` — a sign you can't prove symbolically is a candidate for `numerical-check` (falsify) or `lean-check` (prove). ### 5. Belt-and-suspenders Even on a `.equals() == True`, do a **quick numerical substitution** at one random point as a sanity check against a symbol/transcription bug. A transcription error is the most common real failure. ### 6. Emit the verification report ## Script skeleton (adapt) ```python # uv run --no-project --with sympy python