rz3 0.1.3

Deterministic, exact-rational SMT solver in pure Rust (DPLL(T)/CDCL) with an exact linear-arithmetic core. Zero C dependencies, WASM-deployable, reproducible run-to-run.
Documentation
# 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=30` bit-identical harness). There is no `rand`, no wall-clock-dependent heuristic, and
  no timeout-induced nondeterminism.
- **Portable** — pure Rust with zero native dependencies, so it compiles to `wasm32` and
  embeds without FFI. This is the niche `rz3` was built for: SMT where a C++ solver cannot go.

It is not a drop-in replacement for Z3 — see **[Scope and limitations](#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 handle `SolverResult::Unknown`.
- **Less performance tuning.** Z3 has two decades of engineering; `rz3` favors 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

```toml
[dependencies]
rz3 = "0.1"
```

```rust
use rz3::Rz3Solver;
use rz3::ast::{Expr, Type};
use rz3::SolverResult;

let mut s = Rz3Solver::new();
// x > 0 ∧ x < 0  →  Unsat (exact, deterministic)
let x = || Expr::Var("x".into(), Type::Int);
s.assert(&Expr::Gt(Box::new(x()), Box::new(Expr::Int(0))));
s.assert(&Expr::Lt(Box::new(x()), Box::new(Expr::Int(0))));
assert!(matches!(s.check(), SolverResult::Unsat));
```

There is also an SMT-LIB 2.6 front-end binary (`rz3`) for `.smt2` files.

## Project structure

- `src/ast` — logical and arithmetic expressions (exact `Real(numer, scale)`, no `f64`).
- `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 `rand` and no parallelism in the decision path; all tie-breaks are by index.
- Collections that affect decisions are `BTreeMap`/`BTreeSet` (ordered), never `HashMap`.
- 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=30` harness asserts bit-identical results (SHA-256) across repeated independent solves.

## License

Licensed under either of **MIT** ([LICENSE-MIT](LICENSE-MIT)) or **Apache-2.0**
([LICENSE-APACHE](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). `rz3` is an independent pure-Rust
> implementation and is not affiliated with or derived from Microsoft's Z3.