3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2026-03-22 20:39:11 +00:00
z3/src/nlsat/nlsat_solver.h
Lev Nachmanson 6fb68ac010
Nl2lin - integrate a linear under approximation of a CAD cell by Valentin Promies. (#8982)
* outline of signature for assignment based conflict generation

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* outline of interface contract

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remove confusing construction

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* add material in nra-solver to interface

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* add marshaling from nlsat lemmas into core solver

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* tidy

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* add call to check-assignment

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* Nl2lin (#7795)

* add linearized projection in nlsat

* implement nlsat check for given assignment

* add some comments

* fixup loop

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* updates

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fixes

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* debug nl2lin

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* Nl2lin (#7827)

* fix linear projection

* fix linear projection

* use an explicit cell description in check_assignment

* clean up (#7844)

* Simplify no effect checks in nla_core.cpp

Move up linear nlsat call to replace bounded nlsat.

* t

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* t

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* detangle mess

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* remove the too early return

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* do not set use_nra_model to true

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* remove a comment

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* add a hook to add new multiplication definitions in nla_core

* add internalization routine that uses macro-expanded polynomial representation

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* add internalization routine that uses macro-expanded polynomial representation

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* fixup backtranslation to not use roots

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* call setup_assignment_solver instead of setup_solver

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* debug the setup, still not working

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* updated clang format

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* simplify

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>

* create polynomials with integer coefficients, use the hook to create new monomials

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* integrating changes from master related to work with polynomials

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* add forgotten files

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* Update nlsat_explain.cpp

Remove a duplicate call

* fix

* move linear cell construction to levelwise

* fix

* fix

* Port throttle and soundness fixes from master

- Fix soundness: pop incomplete lemma from m_lemmas on add_lemma failure
- Gracefully handle root atoms in add_lemma
- Throttle check_assignment with failure counter (decrement on success)
- Add arith.nl.nra_check_assignment parameter

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add arith.nl.nra_check_assignment_max_fail parameter

Replace hardcoded failure threshold with configurable parameter (default 10).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* Add cha_abort_on_fail parameter to control failure counter decrement

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* abort nla check_assignment after a set number of allowed failures

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* Add missing AST query methods to Java API (#8977)

* add Expr.isGround() to Java API

Expose Z3_is_ground as a public method on Expr. Returns true when the
expression contains no free variables.

* add Expr.isLambda() to Java API

Expose Z3_is_lambda as a public method on Expr. Returns true when the
expression is a lambda quantifier.

* add AST.getDepth() to Java API

Expose Z3_get_depth as a public method on AST. Returns the maximum
number of nodes on any path from root to leaf.

* add ArraySort.getArity() to Java API

Expose Z3_get_array_arity as a public method on ArraySort. Returns
the number of dimensions of a multi-dimensional array sort.

* add DatatypeSort.isRecursive() to Java API

Expose Z3_is_recursive_datatype_sort as a public method on
DatatypeSort. Returns true when the datatype refers to itself.

* add FPExpr.isNumeral() to Java API

Expose Z3_fpa_is_numeral as a public method on FPExpr. Returns true
when the expression is a concrete floating-point value.

* add isGroundExample test to JavaExample

Test Expr.isGround() on constants, variables, and compound
expressions.

* add astDepthExample test to JavaExample

Test AST.getDepth() on leaf nodes and nested expressions to verify
the depth computation.

* add arrayArityExample test to JavaExample

Test ArraySort.getArity() on single-domain and multi-domain array
sorts.

* add recursiveDatatypeExample test to JavaExample

Test DatatypeSort.isRecursive() on a recursive list datatype and a
non-recursive pair datatype.

* add fpNumeralExample test to JavaExample

Test FPExpr.isNumeral() on a floating point constant and a symbolic
variable.

* add isLambdaExample test to JavaExample

Test Expr.isLambda() on a lambda expression and a plain variable.

* change the default number of failures in check_assignment to 7

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* Fix high and medium priority API coherence issues (Go, Java, C++, TypeScript) (#8983)

* Initial plan

* Add missing API functions to Go, Java, C++, and TypeScript bindings

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* qf-s-benchmark: debug build + seq tracing + seq-fast/nseq-slow trace analysis (#8988)

* Initial plan

* Update qf-s-benchmark: debug build, seq tracing, trace analysis

Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>

* disable linear approximation by default to check the merge

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* set check_assignment to true

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* fix restore_x by recalulating new column values

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* fix restore_x by recalulating new column values

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

* fix a memory leak

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>

---------

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
Co-authored-by: Nikolaj Bjorner <nbjorner@microsoft.com>
Co-authored-by: ValentinPromies <44966217+ValentinPromies@users.noreply.github.com>
Co-authored-by: Valentin Promies <valentin.promies@rwth-aachen.de>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Angelica Moreira <48168649+angelica-moreira@users.noreply.github.com>
Co-authored-by: Copilot <198982749+Copilot@users.noreply.github.com>
Co-authored-by: NikolajBjorner <3085284+NikolajBjorner@users.noreply.github.com>
2026-03-15 06:13:04 -10:00

319 lines
8.8 KiB
C++

/*++
Copyright (c) 2012 Microsoft Corporation
Module Name:
nlsat_solver.h
Abstract:
Nonlinear arithmetic satisfiability procedure. The procedure is
complete for nonlinear real arithmetic, but it also has limited
support for integers.
Author:
Leonardo de Moura (leonardo) 2012-01-02.
Revision History:
--*/
#pragma once
#include "nlsat/nlsat_types.h"
#include "util/params.h"
#include "util/statistics.h"
#include "util/rlimit.h"
#include "util/dependency.h"
namespace nlsat {
class evaluator;
class explain;
class display_assumption_proc {
public:
virtual ~display_assumption_proc() = default;
virtual std::ostream& operator()(std::ostream& out, assumption a) const = 0;
};
struct bound_constraint {
var x;
polynomial_ref A, B;
bool is_strict;
clause* c;
bound_constraint(var x, polynomial_ref& A, polynomial_ref& B, bool is_strict, clause* c) :
x(x), A(A), B(B), is_strict(is_strict), c(c) {}
};
class solver {
struct imp;
struct ctx;
imp * m_imp;
ctx * m_ctx;
solver(ctx& c);
public:
solver(reslimit& rlim, params_ref const & p, bool incremental);
~solver();
/**
\brief Return reference to rational manager.
*/
unsynch_mpq_manager & qm();
/**
\brief Return reference to algebraic number manager.
*/
anum_manager & am();
/**
\brief Return a reference to the polynomial manager used by the solver.
*/
pmanager & pm();
void set_display_var(display_var_proc const & proc);
void set_display_assumption(display_assumption_proc const& proc);
// -----------------------
//
// Variable, Atoms, Clauses & Assumption creation
//
// -----------------------
/**
\brief Create a fresh boolean variable that is not associated with any
nonlinear arithmetic atom.
*/
bool_var mk_bool_var();
literal mk_true();
/**
\brief Create a real/integer variable.
*/
var mk_var(bool is_int);
/**
\brief Create an atom of the form: p=0, p<0, p>0
Where p = ps[0]^e[0]*...*ps[sz-1]^e[sz-1]
e[i] = 1 if is_even[i] is false
e[i] = 2 if is_even[i] is true
\pre sz > 0
*/
bool_var mk_ineq_atom(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even);
/**
\brief Create a literal for the p=0, p<0, p>0.
Where p = ps[0]^e[0]*...*ps[sz-1]^e[sz-1] for sz > 0
p = 1 for sz = 0
e[i] = 1 if is_even[i] is false
e[i] = 2 if is_even[i] is true
*/
literal mk_ineq_literal(atom::kind k, unsigned sz, poly * const * ps, bool const * is_even, bool simplify = false);
/**
\brief Create an atom of the form: x=root[i](p), x<root[i](p), x>root[i](p)
*/
bool_var mk_root_atom(atom::kind k, var x, unsigned i, poly * p);
void inc_ref(bool_var b);
void inc_ref(literal l) { inc_ref(l.var()); }
void dec_ref(bool_var b);
void dec_ref(literal l) { dec_ref(l.var()); }
void inc_ref(assumption a);
void dec_ref(assumption a);
/**
\brief Create a new clause.
*/
void mk_clause(unsigned num_lits, literal * lits, assumption a = nullptr);
// -----------------------
//
// Basic
//
// -----------------------
/**
\brief Return the number of Boolean variables.
*/
unsigned num_bool_vars() const;
/**
\brief Get atom associated with Boolean variable. Return 0 if there is none.
*/
atom * bool_var2atom(bool_var b);
/**
\brief extract free variables from literal.
*/
void vars(literal l, var_vector& vs);
/**
\brief provide access to atoms. Used by explain.
*/
atom_vector const& get_atoms();
/**
\brief Access var -> asserted equality.
*/
atom_vector const& get_var2eq();
/**
\brief expose evaluator.
*/
evaluator& get_evaluator();
/**
\brief Access explanation module.
*/
explain& get_explain();
/**
\brief Access assignments to variables.
*/
void get_rvalues(assignment& as);
void set_rvalues(assignment const& as);
void get_bvalues(svector<bool_var> const& bvars, svector<lbool>& vs);
void set_bvalues(svector<lbool> const& vs);
/**
* \brief Access functions for simplify module.
*/
void del_clause(clause* c);
clause* mk_clause(unsigned n, literal const* lits, bool learned, internal_assumption a);
bool has_root_atom(clause const& c) const;
assumption join(assumption a, assumption b);
void inc_simplify();
void record_levelwise_result(bool success);
void add_bound(bound_constraint const& c);
/**
\brief reorder variables.
*/
void reorder(unsigned sz, var const* permutation);
void restore_order();
/**
\brief Return number of integer/real variables
*/
unsigned num_vars() const;
bool is_int(var x) const;
// -----------------------
//
// Search
//
// -----------------------
lbool check();
lbool check(literal_vector& assumptions);
//
// check satisfiability of asserted formulas relative to state of the nlsat solver.
// produce either,
// l_true - a model is available (rvalues can be ignored) or,
// l_false - a clause (not core v not cell) excluding a cell around rvalues if core (consisting of atoms
// passed to nlsat) is asserted.
// l_undef - if the search was interrupted by a resource limit.
// clause is a list of literals. Their disjunction is valid.
// Different implementations of check are possible. One where cell comprises of linear polynomials could
// produce lemmas that are friendly to linear arithmetic solvers.
//
lbool check(assignment const& rvalues, literal_vector& clause);
// -----------------------
//
// Model
//
// -----------------------
anum const & value(var x) const;
lbool bvalue(bool_var b) const;
bool is_interpreted(bool_var b) const;
lbool value(literal l) const;
// -----------------------
//
// Core
//
// -----------------------
void get_core(vector<assumption, false>& deps);
// -----------------------
//
// Misc
//
// -----------------------
void updt_params(params_ref const & p);
static void collect_param_descrs(param_descrs & d);
const assignment& sample() const;
assignment& sample();
bool apply_levelwise() const;
unsigned lws_spt_threshold() const;
bool lws_witness_subs_lc() const;
bool lws_witness_subs_disc() const;
void reset();
void collect_statistics(statistics & st);
void reset_statistics();
void display_status(std::ostream & out) const;
// -----------------------
//
// Pretty printing
//
// -----------------------
/**
\brief Display solver's state.
*/
std::ostream& display(std::ostream & out) const;
/**
\brief Display literal
*/
std::ostream& display(std::ostream & out, literal l) const;
std::ostream& display(std::ostream & out, unsigned n, literal const* ls) const;
std::ostream& display(std::ostream& out, clause const& c) const;
std::ostream& display(std::ostream & out, literal_vector const& ls) const;
std::ostream& display(std::ostream & out, atom const& a) const;
std::ostream& display_smt2(std::ostream & out, literal l) const;
std::ostream& display_smt2(std::ostream & out, unsigned n, literal const* ls) const;
std::ostream& display_smt2(std::ostream & out, literal_vector const& ls) const;
std::ostream& display_smt2(std::ostream & out) const;
/**
\brief Display variable
*/
std::ostream& display(std::ostream & out, var x) const;
display_var_proc const & display_proc() const;
std::ostream& display_assignment(std::ostream& out) const;
std::ostream& display_var(std::ostream& out, unsigned j) const;
};
};