[0.2.3] - 2026-06-09
Added
oxiz-sat: Generic proof writers (DratWriter / LratWriter)
DratWriter<W>andLratWriter<W>are now generic over anyW: Write + Send, replacing the concreteDratProof/LratProoftypes that were hard-coded toBufWriter<File>.- New
with_writer(w: W)constructors andenable_writer(&mut self, w: W)methods enable in-memory proof capture (e.g. viaCursor<Vec<u8>>), which is the primary driver for the rename. Defaultimpls are specialized onBufWriter<File>so all existing call sites compile unchanged.
oxiz-solver / oxiz-theories: BvMul constant-shift optimization
BvSolver::bv_shl_const(result, a, shift, width)added: encodesa << shiftdirectly from source bits, bypassing the full multiplier circuit.encode_bv_term_recursiveintheory_manager.rsnow detectsbvmul(x, 2^k)and emitsbv_shl_constinstead, reducing the clause count for power-of-2 multiplications.
oxiz-nlsat: Rational root theorem for higher-degree polynomials
Evaluator::find_rootsnow handles polynomials of degree ≥ 3 via a complete rational-root-theorem search (find_rational_roots_univariate), replacing the previous stub that returned an empty set.NlsatSolver::find_rational_rootsadded to the decide module with the same algorithm, wired intofind_roots_for_var.MonotonicityAnalyzer::estimate_derivative_signnow samples the sign at zero for root-free univariate derivatives instead of always returningNone.
oxiz-nlsat: Proper resultant and leading-coefficient extraction
explain.rs::leading_coefficientnow delegates toPolynomial::leading_coeff_wrt(var)instead of cloning the full polynomial.explain.rs::resultantnow callsPolynomial::resultant(q, var)instead of always returning zero.
oxiz-opt: Full term-level optimization pipeline
OptContext::check_satis now a real solver call viaoxiz_solver::Solver; previously it always returnedUnknown.OptContext::optimize_maxsmtimplements a binary-search selector-variable encoding: fresh boolean/cost variables per soft constraint, withb_i → t_iimplications andite-encoded cost functions, then binary search on the total cost budget.OptContext::optimize_single_objectivenow delegates tooxiz_solver::Optimizer::optimize.OptContext::optimize_paretonow delegates tooxiz_solver::Optimizer::pareto_optimize.OptResult::Unboundedvariant added.OptContext::pareto_front()accessor added.OptContext::config()accessor added.OptContextgains a publicterms: TermManagerfield,next_sel_id, andpareto_frontcache.- Internal helpers
term_id_to_model_valueandterm_id_to_weightadded for converting solver-modelTermIds toModelValue/Weight.
oxiz-theories: Simplex optimization extension (simplex_opt.rs)
- New module
simplex_optaddsSimplex::optimize_linexpr(&mut self, obj: &LinExpr) -> SimplexOptStatusimplementing the primal simplex optimization phase with Bland's rule. SimplexOptStatusenum (Optimal,Unbounded,Infeasible,Unknown) published from the arithmetic module.LraOptimizer::optimize_minnow callsoptimize_linexprinstead of returning a zero placeholder.
oxiz-theories: Correct Simplex push/pop with tableau snapshots
Simplex::pushnow saves a full tableau snapshot (saved_tableaux) alongside the assignment cache, so pivots performed duringcheck()inside a pushed scope are correctly undone onpop().Simplex::resetclears bothcached_assignmentsandsaved_tableaux.
oxiz-theories: Sound Nelson-Oppen equality propagation
ArithSolver::notify_equalitynow encodesx = yinto the simplex tableau asx - y <= 0andy - x <= 0instead of ignoring the notification.- New
ArithSolver::derive_shared_equalities(&mut self)performs probe-and-pop model-based equality detection: emitsx = yonly when bothx < yandx > yare infeasible. ArithSolverstores accumulated notified equalities inshared_equalities: Vec<EqualityNotification>, properly backed out onpop().ContextStatetracksnum_shared_equalitiesfor rollback.
oxiz-theories: BvSolver soundness and incremental improvements
BvSolver::assert_uge(lhs, rhs)— new unsigned-greater-than-or-equal comparator; encodes asbool_ule(rhs, lhs)and inserts a NOT literal.BvSolver::get_valuenow reads from theself.last_sat_modelsnapshot instead of the live trail, fixing all-zero readback that occurred after backtracking.BvSolver::check()soundness fix: capturescommitted_trailandlearned_beforebefore each SAT probe; callsrestore_to_trail_sizeandforget_learned_sinceafter every probe to discard search residue that caused false UNSAT in incremental solving.
oxiz-solver: Context::eval_in_model
- New
pub fn eval_in_model(&mut self, term: TermId) -> Option<TermId>evaluates a term against the current SAT model; returnsNonewhen no model is available.
oxiz-spacer: Real BMC and k-induction
BmcResult::Unknownvariant added for inconclusive results.BmcError::NoInitRuleadded.Bmc::check_bad_at_depthreplaced: now buildsInit(s₀) ∧ ⋀Trans(sᵢ,sᵢ₊₁) ∧ Bad(sₖ)and callsSmtSolver::check_sat; returnsUnsafeonly when the solver confirms SAT.Bmc::check_kinductionreplaced with a sound k-induction procedure: base cases checked via BMC + inductive step⋀P(sᵢ) ∧ ⋀Trans ∧ Bad(sₖ)UNSAT required forSafe.Bmc::run_kinductionadded to loop from depth 1 tomax_depth.extract_modelusesContext::eval_in_modelfor concrete counterexample extraction.SmtSolver::terms()accessor added;SmtSolverno longer holds a duplicateTermManagerreference.- Per-step variable helpers
make_step_vars/subst_from_argsadded.
Changed
oxiz-sat: DratProof / LratProof renamed to DratWriter / LratWriter (BREAKING)
- All internal usages in
drat_inprocessing.rsandlib.rsupdated. - The rename avoids a name collision with
oxiz-proof::DratProof.
oxiz-solver: Optimizer convergence guard
- Both integer and real objective search loops now break immediately when model evaluation does not produce a concrete value, preventing infinite looping on abstract terms.
Dependencies
oxiarc-deflateandoxiarc-brotlibumped from 0.3.1 to 0.3.3.sysinfoupdated from 0.38 to 0.39.rhaiupdated from 1.24 to 1.25 (inoxiz-core).wideupdated from 1.3 to 1.5 (inoxiz-core).lruupdated from 0.17 to 0.18.pdf-writerupdated from 0.14 to 0.15.
Fixed
oxiz-sat: Hardcoded absolute proof paths replaced with std::env::temp_dir()
- All four proof-logger tests now use portable temp paths instead of
/tmp/test_*.proof.
oxiz-theories: BvSolver incremental soundness
- Previously, a satisfying assignment from one incremental
check()probe would persist on the trail and contradict constants asserted in the next probe, yielding a false UNSAT. Fixed by rolling back the trail (restore_to_trail_size) and forgetting learned clauses (forget_learned_since) after every probe. Regression test:test_incremental_mul_aux_diseq_then_const_is_sat.
oxiz-theories: Simplex pop() no longer corrupts tableau after in-scope pivots
- The previous heuristic (filtering stale tableau entries by variable index) was insufficient when pivots changed which variables were basic. The new snapshot-based restore is correct by construction.
Full Changelog: v0.2.2...v0.2.3