Symbolic Check: Prove/Refute a Self-Authored Algebra Step with a CAS
SkillDev toolsUse 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.
Available today. Use it from your connected AI after setup.
No other account needed.
Connect ahel once, and every AI you use reads what you have installed.
Then ask your AI: use the Symbolic Check: Prove/Refute a Self-Authored Algebra Step with a CAS skill
What this skill tells your AI
The instructions your AI receives, as published by flonat/flonat-research in skills/symbolic-check/SKILL.md and read by ahel’s review.
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-unverifiedfor 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, derivativediff(f,x) == g, limitlimit(f,x,a) == L, signsign(diff(f,x))over a domain, or closed formexpr == 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, reportINCONCLUSIVE (numerically consistent, symbolically undecided); if any is far from 0, that's a FALSIFIED witness. - Never upgrade
NonetoVERIFIED. Undecided is undecided.
4. Comparative-static / monotonicity signs
- Compute
d = diff(f, x). Ask whetherdhas 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 reportINCONCLUSIVE (sign consistent on N points)— a sign you can't prove symbolically is a candidate fornumerical-check(falsify) orlean-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)
# uv run --no-project --with sympy python <script>.py
import sympy as sp
mu, mumax, rho = sp.symbols('mu mumax rho', positive=True) # DECLARE the domain
# --- identity / closed-form ---
A = mu / sp.sqrt(rho); B = mumax # claim: threshold solves A == B
rho_star = sp.solve(sp.Eq(A, B), rho) # -> [mu**2/mumax**2]
print("rho* =", rho_star, " expected (mu/mumax)**2:", (mu/mumax)**2)
print("identity holds:", (rho_star[0] - (mu/mumax)**2).equals(0)) # True / False / None
# --- derivative sign (monotonicity) ---
Phi = lambda z: (1 + sp.erf(z/sp.sqrt(2)))/2 # standard normal CDF
Q = Phi(mu/sp.sqrt(rho)); d = sp.diff(Q, rho)
print("dQ/drho =", sp.simplify(d), " sign<0 on domain (mu>0):", sp.ask(sp.Q.negative(d), sp.Q.positive(mu)))
Anti-Patterns
- Don't read
simplify(A - B) != 0as FALSIFIED — that's simplify giving up. Use.equals(). - Don't upgrade a
None(undecided) to VERIFIED. Report INCONCLUSIVE. - Don't verify a sign/closed-form without declaring the symbol assumptions — the domain is part of the claim, and the wrong domain gives the wrong answer.
- Don't skip the numerical sanity substitution — it catches transcription bugs a symbolic pass can hide.
- Don't use bare
python3— useuv run --no-project --with sympy python. - Don't force a hard theorem through the CAS — if it needs real reasoning (not symbolic manipulation), escalate to
lean-check(R3) ordomain-reviewer.
Output — Verification Report (shared *-check shape)
Write to reviews/<scope>/verify-symbolic/<YYYY-MM-DD-HHMM>.md:
claim: <exact symbolic statement + declared symbol domains>
method: R2 symbolic/CAS (sympy .equals() [+ numeric sanity at <k> points])
verdict: VERIFIED | FALSIFIED | INCONCLUSIVE (numerically consistent, symbolically undecided) | ERROR
evidence: <simplified form / witness point that disproves / the derived closed form>
reproduce: uv run --no-project --with sympy python experiments/<script>.py
Verification (did this skill work?)
- Verdict is one of the four;
VERIFIEDis emitted only on.equals() == True(or an exactsolve/limitmatch), never onNone. - A numerical sanity substitution accompanies every VERIFIED.
- If feeding a paper, the confirmed closed form / sign is the value that goes in (and any derived constant is emitted via a macro,
no-hardcoded-results).
Worked example — 2026-07-04 (median-collapse paper)
- Closed-form threshold: claim
ρ* = (μ_med/μ_max)²solvesΦ(μ_med/√ρ) = Φ(μ_max).solve(μ_med/√ρ = μ_max, ρ)→μ_med²/μ_max²;.equals()→ VERIFIED. - Homogeneous monotonicity (Prop 3.1):
d/dρ Φ(μ/√ρ) = φ(μ/√ρ)·μ·(−½ρ^{-3/2}), negative forμ>0→ sign VERIFIED underQ.positive(mu)(numeric-confirmed on the domain where sympy hesitates). - These are the algebra rungs beneath the theorems
numerical-checkstress-tested andlean-checkcould formalize.
Signals
- GitHub stars
- 133
- Forks
- 24
- Last commit
- Aug 2026
Advanced
- Catalog kind
- skill
- Gateway key
symbolic-check- Source
- github.com/flonat/flonat-research