3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-11-25 23:19:32 +00:00

revamp stellensatz to use polynomals

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2025-11-12 20:21:42 -08:00
parent 21b36868b5
commit c7084e9998
4 changed files with 397 additions and 542 deletions

File diff suppressed because it is too large Load diff

View file

@ -5,9 +5,9 @@
#pragma once
#include "util/scoped_ptr_vector.h"
#include "math/dd/dd_pdd.h"
#include "math/lp/nla_coi.h"
#include "math/lp/int_solver.h"
#include "math/polynomial/polynomial.h"
#include <variant>
namespace nla {
@ -26,7 +26,6 @@ namespace nla {
lbool solve_lia();
bool update_values();
vector<std::pair<lpvar, rational>> m_to_refine;
void saturate_basic_linearize();
public:
solver(stellensatz &s) : s(s) {};
void init();
@ -39,12 +38,11 @@ namespace nla {
solver m_solver;
// factor t into coeff*x^degree*p + q, such that degree(x, q) < degree,
// factor t into x^degree*p + q, such that degree(x, q) < degree,
struct factorization {
rational coeff;
unsigned degree;
lp::lar_term p;
lp::lar_term q;
dd::pdd p, q;
};
struct external_justification {
@ -60,6 +58,10 @@ namespace nla {
lp::constraint_index ci;
rational mul;
};
struct multiplication_var_justification {
lp::constraint_index ci;
lpvar v;
};
struct multiplication_justification {
lp::constraint_index left, right;
};
@ -73,16 +75,32 @@ namespace nla {
gcd_justification,
addition_justification,
multiplication_const_justification,
multiplication_var_justification,
multiplication_justification
>;
using term_offset = std::pair<lp::lar_term, rational>;
struct constraint {
dd::pdd p;
lp::lconstraint_kind k;
justification j;
};
coi m_coi;
scoped_ptr_vector<justification> m_justifications;
void add_justification(lp::constraint_index ci, justification const &j) {
VERIFY(ci == m_justifications.size());
m_justifications.push_back(alloc(justification, j));
}
vector<rational> m_values;
dd::pdd_manager pddm;
vector<constraint> m_constraints;
dd::pdd to_pdd(lpvar v);
lpvar mk_monomial(svector<lpvar> const &vars);
void init_monomial(unsigned mon_var);
term_offset to_term_offset(dd::pdd const &p);
lp::constraint_index add_constraint(dd::pdd p, lp::lconstraint_kind k, justification j);
lp::constraint_index add_var_bound(lp::lpvar v, lp::lconstraint_kind k, rational const &rhs, justification j);
struct eq {
bool operator()(unsigned_vector const& a, unsigned_vector const& b) const {
return a == b;
@ -92,55 +110,30 @@ namespace nla {
u_map<unsigned_vector> m_mon2vars;
bool is_mon_var(lpvar v) const { return m_mon2vars.contains(v); }
unsigned m_max_monomial_degree = 0;
vector<svector<lp::constraint_index>> m_occurs; // map from variable to constraints they occur.
bool is_new_inequality(vector<std::pair<rational, lpvar>> lhs, lp::lconstraint_kind k, rational const &rhs);
// initialization
void init_solver();
void init_vars();
void init_monomial(unsigned mon_var);
void init_occurs();
void init_occurs(lp::constraint_index ci);
void eliminate_variables();
lp::lpvar select_variable_to_eliminate(lp::constraint_index ci);
unsigned degree_of_var_in_constraint(lpvar v, lp::constraint_index ci) const;
unsigned degree_of_var_in_monomial(lpvar v, lpvar mi) const;
factorization factor(lpvar v, lp::constraint_index ci);
lp::lpvar divide(lpvar v, unsigned degree, lpvar mi);
factorization factor(lpvar v, lp::constraint_index ci);
bool constraint_is_true(lp::constraint_index ci) const;
// additional variables and monomials and constraints
using term_offset = std::pair<lp::lar_term, rational>; // term and its offset
svector<lp::lpvar> expand_monomial(svector<lp::lpvar> const & vars);
lpvar mk_monomial(svector<lp::lpvar> const& vars);
lpvar mk_monomial(svector<lp::lpvar> const &vars, lp::lpvar j);
lpvar mk_term(term_offset &t);
void gcd_normalize(vector<std::pair<rational, lpvar>> &t, lp::lconstraint_kind k, rational &rhs);
lp::constraint_index add_ineq(justification const& just, lp::lar_term &t, lp::lconstraint_kind k, rational const &rhs);
lp::constraint_index add_ineq(justification const &just, lpvar j, lp::lconstraint_kind k,
rational const &rhs);
lp::constraint_index assume(lp::lar_term &t, lp::lconstraint_kind k, rational const &rhs);
lp::constraint_index normalize_ineq(lp::constraint_index ci);
lp::constraint_index gcd_normalize(lp::constraint_index ci);
lp::constraint_index assume(dd::pdd const& p, lp::lconstraint_kind k);
lp::constraint_index add(lp::constraint_index left, lp::constraint_index right);
lp::constraint_index multiply(lp::constraint_index ci, rational const &mul);
lp::constraint_index multiply(lp::constraint_index left, lp::constraint_index right);
lp::constraint_index multiply_var(lp::constraint_index ci, lpvar x);
bool is_int(svector<lp::lpvar> const& vars) const;
rational cvalue(lp::lar_term const &t) const;
rational mvalue(lp::lar_term const &t) const;
rational cvalue(svector<lpvar> const &prod) const;
rational mvalue(svector<lpvar> const &prod) const;
rational cvalue(dd::pdd const& p) const;
lpvar add_var(bool is_int);
// lemmas
@ -162,12 +155,11 @@ namespace nla {
std::ostream& display(std::ostream& out) const;
std::ostream& display_product(std::ostream& out, svector<lpvar> const& vars) const;
std::ostream& display_constraint(std::ostream& out, lp::constraint_index ci) const;
std::ostream& display_constraint(std::ostream& out, lp::lar_term const& lhs,
lp::lconstraint_kind k, rational const& rhs) const;
std::ostream& display(std::ostream &out, term_offset const &t) const;
std::ostream& display(std::ostream &out, justification const &bounds) const;
std::ostream& display_constraint(std::ostream& out, constraint const& c) const;
std::ostream &display(std::ostream &out, justification const &j) const;
std::ostream &display_var(std::ostream &out, lpvar j) const;
std::ostream &display_lemma(std::ostream &out, lp::explanation const &ex, vector<ineq> const &ineqs);
std::ostream &display(std::ostream &out, term_offset const &t) const;
public:
stellensatz(core* core);