A division routine that silently returns 0.0 instead of the right answer is worse than one that panics — the panic gets noticed.
Today we released OxiZ 0.3.0 — a large hardening-and-capability wave built directly on 0.2.4’s production-readiness audit. Confirmed at release time: 8,119 tests passing, 8 skipped, plus 106 doc-tests, all --all-features, clippy/rustdoc -D warnings clean.
No C. No C++. No Fortran. OxiZ reimplements Z3 entirely in Rust — the SAT core, theory solvers, quantifier instantiation, optimization, and proof system are all memory-safe Rust you can read end to end. 0.3.0 keeps auditing that Rust against itself: this release’s soundness fixes came from the same adversarial mindset as 0.2.4’s, turned on the code 0.2.4 shipped.
Why OxiZ 0.3.0 is a game changer
The 0.2.4 audit closed a first wave of silent-wrong-answer bugs. Going deeper into the same crates surfaced a second wave — smaller in scope, just as dangerous:
ieee754_full’sdiv128kept its running remainder in a bareu128and shifted left before subtracting, dropping bit 127 whenever the remainder’s MSB was set — every division whose true quotient fell in(0.5, 1), like10/3or1/3, silently returned0.0- Simplex’s
set_lower/set_upperguarded their write withif idx < self.lower.len()— for any index at or past the array’s current length, the bound-setting call was silently dropped instead of applied ArithSolver::pop()truncatedvar_to_termbut left staleterm_to_varentries; becausesimplex.pop()recyclesVarIds, a replayed stale mapping could attach a constraint to the wrong, recycled variableresolution::resolve()deleted every complementary literal pair found anywhere in the resolvent, not just the pair being resolved on — silently dropping unrelated literals that happened to share a variable- NIA branch-and-bound picked its branching variable with an f64 tolerance window instead of exact
BigRational::is_integer(), misjudging integrality near a boundary
0.3.0 ends all of that — plus it adds real decision procedures where OxiZ used to fall through to Unknown. The results, re-measured against a real z3 4.15.4 binary on bench/z3_parity:
qf_fp: 1/10 → 10/10 — a new concrete floating-point model finder, combined with thediv128fixqf_s: 3/10 → 10/10 — a new ground string decision procedure with verified modelsAUFLIA2/10 → 7/10,UFLIA7/20 → 14/20,UFLRA2/10 → 5/10 — MBQI SAT certification- Extended suite (168 benchmarks / 19 logics): 154 Correct / 0 Wrong / 12 Inconclusive / 2 Timeout / 0 Error — zero soundness disagreements on every decisive comparison, up from 122 Correct / 1 Wrong / 3 process crashes at the 0.2.4 baseline
- Quickstart core (8 logics / 88 benchmarks): 88/88 (100%) Correct, up from 72/88
This is not a “100% parity” claim — three quantified logics (AUFLIA, UFLIA, UFLRA) still have honest Unknown/Timeout gaps. Every gap is disclosed in TODO.md, never silently rounded up.
Technical Deep Dive: where the new decision procedures live
Ground string solving (oxiz-theories/src/string/ground_solver.rs). Gathers a formula’s string constraints, builds a candidate model via definitional propagation and concat-splitting by known operand lengths, then runs a per-variable regular-constraint intersection search reusing the existing Brzozowski-derivative automaton engine. Crucially, it verifies the candidate by concretely evaluating every assertion before it is ever allowed to return Sat — it can only add newly-verified Sat answers, never mask a genuine Unsat.
Concrete FP model finder (oxiz-solver/src/solver/check_fp_model.rs). Pins every FP-sorted term to a bit-exact IEEE-754 value: definitional-equality propagation for variables, the bit-exact engine for operations, predicate-driven witness synthesis for free NaN/Infinity-typed variables. Reports Sat only after verifying every assertion — honest Unknown otherwise, since there’s no complete FP theory in the CDCL(T) core.
MBQI SAT certification. A real completeness certifier for quantified-logic verdicts, built from bounded-box enumeration over finite-interval Int variables, essentially-uninterpreted range-bound detection, and monotone-guard analysis — the difference between “we didn’t find a counterexample” and “we can prove none exists.”
Simplex/ArithSolver hardening. A new ensure_var(idx) chokepoint routes every per-variable-array write through one place that grows assignment/lower/upper/basic in lockstep, so a stale or out-of-range index can neither be silently dropped nor panic. pop() now drains var_to_term’s tail and removes each drained term from term_to_var in lockstep, an O(delta) trail-based undo that closes the recycled-VarId bug above.
Getting Started
Add OxiZ to your project:
cargo add oxiz
Try the new (get-consequences ...) SMT-LIB command — it extracts the unit consequences over queried variables entailed by the current assertions plus a set of assumptions:
use oxiz_solver::Context;
let mut ctx = Context::new();
let output = ctx.execute_script(r#"
(set-logic QF_UF)
(declare-const a Bool)
(declare-const b Bool)
(declare-const c Bool)
(assert (=> a b))
(assert (=> b c))
(get-consequences (a) (b c))
"#).expect("script should parse and run");
assert_eq!(output[0], "sat");
// output[1] reports both (=> a b) and (=> a c) as consequences of assuming `a`
Feature flags layer in the heavier machinery: nlsat for nonlinear arithmetic, optimization for MaxSMT/OMT, spacer for CHC model checking, proof for DRAT/Alethe/LFSC export. Use full to enable everything.
What’s New in 0.3.0
Added
(get-consequences ...)SMT-LIB command and end-to-end:namedassertion support (Context::assert_named).- Regex sublanguage support for the string theory, plus the ground string decision procedure described above.
- The concrete FP model finder and MBQI SAT certification described above.
- Real quantifier elimination: Ferrante-Rackoff and Loos-Weispfenning virtual substitution for LRA, datatype constructor case-split QE, three sound BV QE strategies, and model-based interpolation via exhaustive Boolean expansion.
- Spacer: MIC (Minimal Inductive Clause) generalization, and a genuine multi-threaded parallel PDR portfolio replacing the previous single-process fallback.
oxiz-wasmhard-preemptible solving — a dedicated Web Worker plusSharedArrayBuffer-backed cooperative cancellation, since a synchronous, non-yielding solve loop meantsetTimeout-based timeouts could never actually preempt anything on a single-threaded JS host.oxiz-cli:--minimize-core,--enumerate-models/--max-models, a wall-clock--timeoutsupervisor, and--ml-tactic-selection(opt-in) now genuinely wired to a trainable decision-tree tactic selector.
Fixed
- The soundness fixes described above, plus: exact
BigRational-based floor/ceil and real Euclidean polynomial division/GCD inoxiz-math; a real propositional Craig interpolant for MBI instead of a placeholder; McMillan interpolation now colors axioms from the caller’s actual A/B partition; two process-crash panics (a SAT theory-conflict-with-unassigned-literal panic, a simplex out-of-bounds panic) fixed so all three previously-crashing benchmarks now run to completion. - Confirmed-dead GPU scaffolding (
cuda/opencl/vulkanflags with zero references anywhere in the workspace) deleted rather than left as a misleading placeholder.
Full itemized detail, crate by crate, is in the CHANGELOG.
Tips
- Re-run FP regression suites. If you rely on
fp.div,fp.rem, or fused multiply-add, this release fixes a real bit-dropping bug indiv128— any quotient landing in(0.5, 1)was silently wrong before. - String constraints now actually solve. If
Concat/Length/regex-membership queries previously fell through toUnknown, upgrade —qf_swent from 3/10 to 10/10 on the parity suite. get-consequencesneeds no feature flag. It’s part of the core SMT-LIB command set — see the example above.oxiz-wasmtimeouts now really preempt. If you were working around the old cooperative-only cancellation with a watchdog process, the newPreemptibleSolver+Worker.terminate()path makes that unnecessary.- Check
TODO.mdbefore relying on quantified logics.AUFLIA/UFLIA/UFLRAimproved substantially this release but are not at 100% — every remaining gap is an honestUnknown/Timeout, itemized with file:line detail.
This is the foundation
OxiZ is the formal-reasoning backbone of the COOLJAPAN ecosystem. OxiLean uses it as its SMT proof backend; OxiRS leans on it for validation; Legalis-RS uses it for legal formal verification, and OxigenAI builds on Legalis-RS and OxiZ together. OxiCAD, OxiCar, OxiEDA, OxiAutoRS, OxiMed, and OxiQuant all depend on oxiz-core/oxiz-solver/oxiz-proof for constraint solving. Underneath, OxiZ relies on pure-Rust OxiARC for compression. The whole stack is C/C++/Fortran-free — sovereign from the SAT core all the way up to the application.
Repository: https://github.com/cool-japan/oxiz
Star the repo if you want an SMT solver that tells you when it doesn’t know, rather than confidently telling you the wrong thing.
Pure Rust formal reasoning is here — audited, honest, and sovereign.
— KitaSan at COOLJAPAN OÜ July 22, 2026