rz3 — a deterministic, exact-rational SMT solver in pure Rust
rz3 is an SMT (Satisfiability Modulo Theories) solver written entirely in safe Rust, with
no C/C++ dependencies. It is built around three properties that are uncommon together:
- Exact — arithmetic is computed over arbitrary-precision rationals (
num-rational/num-bigint). There is no floating-point in the decision core, so there are no rounding artifacts and no false verdicts from numeric error. - Deterministic — the same input yields the same result on every run (verified by an
n=30bit-identical harness). There is norand, no wall-clock-dependent heuristic, and no timeout-induced nondeterminism. - Portable — pure Rust with zero native dependencies, so it compiles to
wasm32and embeds without FFI. This is the nicherz3was built for: SMT where a C++ solver cannot go.
It is not a drop-in replacement for Z3 — see Scope and limitations.
What it does
rz3 is a lazy SMT solver (DPLL(T)): a CDCL SAT core drives a set of theory solvers.
| Layer | Status |
|---|---|
| CDCL SAT core (deterministic VSIDS, restarts) | stable |
| Linear arithmetic (LRA/LIA) — exact Simplex, δ-rational strict bounds, lexicographic anti-cycling | production-oriented core; may return Unknown on unresolved degeneracy/budget limits |
| Difference logic (negative-cycle detection) | complete |
| Uninterpreted functions + equality (EUF, congruence closure) | stable |
| Arrays (read-over-write) | core |
| Bit-vectors | partial |
| Strings | partial |
| Floating-point (ground) | partial |
| Quantifiers (instantiation) | partial |
| Non-linear arithmetic | partial |
SMT-LIB 2.6 front-end (set-logic, declare/define-fun, assert, check-sat, get-model, get-value, push/pop, …) |
subset |
The linear-arithmetic core is the most mature part of the solver. It uses exact rationals,
symbolic strict bounds and deterministic pivoting, and it includes regression tests for
termination-sensitive cases. Some unresolved degenerate or disequality-heavy cases may still
return Unknown; Unknown is treated as a sound non-answer, not as Sat or Unsat.
Scope and limitations (vs. Z3)
Z3 (Microsoft Research) is a mature, ~17-year solver. rz3 deliberately implements the
subset needed for deterministic, exact, embeddable reasoning — much as a focused tool covers
the part of a large system that a given workload actually needs. Honestly, relative to Z3:
- Smaller theory coverage. Bit-vectors, strings, floating-point, quantifiers and non-linear arithmetic are partial; Z3's are complete and battle-tested.
- No optimization (
maximize/minimize, à la νZ). - Partial proof/unsat-core/interpolation support.
- A subset of SMT-LIB 2.6, not the full standard.
- Some LRA cases can return
Unknown. This is intentional for unresolved pivot-budget or disequality-repair cases; callers must handleSolverResult::Unknown. - Less performance tuning. Z3 has two decades of engineering;
rz3favors correctness, exactness and determinism over raw speed.
What rz3 offers that a C++ solver does not: exact (non-floating-point) verdicts, run-to-run
reproducibility, and wasm32/no-FFI deployability with zero native dependencies.
Usage
[]
= "0.1"
use Rz3Solver;
use ;
use SolverResult;
let mut s = new;
// x > 0 ∧ x < 0 → Unsat (exact, deterministic)
let x = ;
s.assert;
s.assert;
assert!;
There is also an SMT-LIB 2.6 front-end binary (rz3) for .smt2 files.
Project structure
src/ast— logical and arithmetic expressions (exactReal(numer, scale), nof64).src/sat— deterministic CDCL SAT engine.src/theory— theory solvers (LRA Simplex, EUF, arrays, bit-vectors, FP, strings, …).src/parser— SMT-LIB 2.6 lexer/parser.
Determinism & exactness guarantees
- No
randand no parallelism in the decision path; all tie-breaks are by index. - Collections that affect decisions are
BTreeMap/BTreeSet(ordered), neverHashMap. - Arithmetic is
num-rational/num-bigint; strict inequalities use a symbolic infinitesimalδ(Dutertre–de Moura), and Simplex anti-cycling uses a lexicographicε-perturbation — both symbolic, so results stay exact. - An
n=30harness asserts bit-identical results (SHA-256) across repeated independent solves.
License
Licensed under either of MIT (LICENSE-MIT) or Apache-2.0 (LICENSE-APACHE) at your option.
"Z3" is a generic, widely-shared name (the Zuse Z3 of 1941 was the first programmable computer; Z3 is also Microsoft Research's SMT solver).
rz3is an independent pure-Rust implementation and is not affiliated with or derived from Microsoft's Z3.