exprtest
exprtest provides fast predicates for mathematical expressions (including exact numeric ones). Its currently primary API, zerotest(), returns True only for a proved zero. By default it returns False for either a proved nonzero value or strong one-sided evidence of nonzeroness, and None when neither conclusion is available. Use confidence="certified" when False must mean proved nonzero.
The package combines specialized SymPy-based exact methods with rigorous Arb/Acb ball arithmetic from python-flint. Numerical guesses and probabilistic evidence never become a proof without an independent certificate. The default probable policy may use strong one-sided nonzero evidence for a False result; users can request certified-only Boolean semantics explicitly.
Installation
pip install exprtest
Install the rigorous Arb/FLINT backend when you want ball-arithmetic and FLINT-accelerated proofs:
pip install "exprtest[flint]"
For development with the full backend:
pip install -e ".[dev]"
pytest
Quick start
import sympy as sp
from exprtest import is_algebraic, is_prime, zerotest
x = sp.symbols("x")
assert zerotest(0) is True
assert zerotest(sp.pi) is False
assert zerotest(sp.Function("f")(x)) is None
assert is_prime(97) is True
assert is_algebraic(sp.sqrt(2)) is True
assert is_algebraic(sp.pi) is False
For a complete executable example, see
examples/quickstart.py.
Proof semantics
zerotest(expr) defaults to probable semantics: strong one-sided NONZERO_LIKELY evidence may map to False; probabilistic zero-like evidence is never promoted to True. Use zerotest(expr, confidence="certified") when both Boolean outcomes must be certified. Use profile_zerotest() when you need the method, evidence, or stage timings.
from exprtest import profile_zerotest
profile = profile_zerotest(sp.exp(sp.sqrt(2), evaluate=False))
assert profile.result is False
print(profile.classification.method)
print(profile.classification.evidence)
The distinction between exact proof, rigorous enclosure, probabilistic evidence, and heuristic candidate generation is described in
docs/soundness.md.
What the fast oracle handles
The normal oracle uses bounded, structure-specific methods rather than general symbolic simplification. Important classes include exact rational arithmetic, small algebraic towers and radicals, bounded polynomial/rational identities, assumption-aware nonzero and definedness proofs, roots of unity and exact trigonometric/power identities, branch-safe logarithmic/exponential relations, selected exact special-function values, bounded exponential-independence theorems, rigorous Arb/Acb enclosures, and finite-field testing for suitable rational functions.
Potentially expensive stages are admitted by structural budgets. Sparse tower arithmetic, cached expression fingerprints, per-call fact memoization, and adaptive precision selection keep common cases inexpensive.
Function-property knowledge
exprtest includes a small registry of SymPy-native function facts, including selected real/sign properties, complex-domain restrictions, and simple pole sets. The active entries are regression-tested against the documented SymPy semantics used by the package. This improves zerotest() as well as public predicates such as is_real() and is_integer() without adding a runtime dependency. The registry is documented in docs/function_facts.md.
A capability overview is available in
docs/capabilities.md.
Number predicates
The package exposes tri-state predicates for common number domains:
from exprtest import (
ElementOf,
is_algebraic,
is_integer,
is_prime,
is_rational,
is_real,
number_kind,
)
Each predicate returns True, False, or None according to what the bounded proof engine can establish. ElementOf() performs lightweight membership simplification, and number_kind() distinguishes values proved algebraic, proved transcendental, or unresolved.
See
docs/api.md
for the supported public interface.
Performance model
zerotest() is intended to be a fast heuristic, so does not call general sympy.simplify(), trigsimp(), or together() on its latency-sensitive path. Expensive algebraic operations are size-gated and time-bounded. Stronger separation bounds and higher Arb precision are requested only when cheaper certificates are insufficient.
benchmarks/benchmark_zerotest.py measures cold and repeated-call throughput, median latency, p95 latency, and verdict counts. Benchmark numbers are machine specific; routing and proof-stage assertions in the test suite enforce the performance architecture independently of wall-clock timing. CI also records branch coverage and runs a separate structural performance-contract job.
More detail is in
docs/performance.md.
Limitations
exprtest is intentionally incomplete. General symbolic identities with free variables, high-degree algebraic extensions, difficult branch-sensitive complex identities, and transcendental combinations outside known theorems may return None. Algebraic independence questions that are unknown in mathematics remain unknown to the package. And, of course, zero testing in general is undecidable.
See
docs/limitations.md
for the main boundaries and planned extensions.
Documentation
APIArchitectureCapabilitiesSoundnessPerformanceAssumptions and branchesLimitationsDevelopment
License
exprtest is free software licensed under the GNU General Public License v3.0 (GPL-3.0-only). See LICENSE for the full license text.
Metadata
Release files for exprtest 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| exprtest-0.1.0.tar.gz | 104.2 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| exprtest-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 191.8 kB
Release files / exprtest-0.1.0.tar.gz
| Download URL | exprtest-0.1.0.tar.gz |
|---|---|
| Size | 104.2 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
268354fd84944628e2b4d760950807bb7c1fc77cc5f2ecd4658835be68b2d63a
|
|
BLAKE2b-256 checksum How to use checksums |
de1fe2d7b39fdc72db4ee340cf31fa3b902dd8906ad3ebbe638a8573b6bf3502
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.
Transparency logRelease files / exprtest-0.1.0-py3-none-any.whl
| Download URL | exprtest-0.1.0-py3-none-any.whl |
|---|---|
| Size | 87.7 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
52f9705017af22bc3d20c270656fe8666a533264d99e8a06b12ca968a27fd91e
|
|
BLAKE2b-256 checksum How to use checksums |
8d289d88b30882812ed0646051f3cf0151c3b5c83631f1aa110d544fbc159865
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
Yes |
| Uploaded via |
twine/7.0.0 CPython/3.13.14
|
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
PyPI Publish Attestation
PyPI verified that this artifact, at this checksum, originated from the publisher listed below.
Signed by GitHub Actions, verified by PyPI on Aug 28, 2026.
Transparency log