mirror of
https://github.com/Z3Prover/z3
synced 2025-11-25 15:09:32 +00:00
revamp stellensatz to use polynomals
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
21b36868b5
commit
c7084e9998
4 changed files with 397 additions and 542 deletions
|
|
@ -1908,6 +1908,36 @@ namespace dd {
|
|||
return m->mk_var(var())*h + l;
|
||||
}
|
||||
|
||||
void pdd::merge(unsigned_vector& lo, unsigned_vector& hi, unsigned_vector& common) {
|
||||
std::sort(lo.begin(), lo.end());
|
||||
std::sort(hi.begin(), hi.end());
|
||||
unsigned ir = 0, jr = 0;
|
||||
for (unsigned i = 0, j = 0; i < lo.size() || j < hi.size(); ) {
|
||||
if (i == lo.size())
|
||||
hi[jr++] = hi[j++];
|
||||
else if (j == hi.size())
|
||||
lo[ir++] = lo[i++];
|
||||
else if (lo[i] == hi[j]) {
|
||||
common.push_back(lo[i]);
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
else if (lo[i] > hi[j])
|
||||
hi[jr++] = hi[j++];
|
||||
else
|
||||
lo[ir++] = lo[i++];
|
||||
}
|
||||
lo.shrink(ir);
|
||||
hi.shrink(jr);
|
||||
}
|
||||
|
||||
pdd pdd::mul(unsigned_vector const& vars) const {
|
||||
pdd r = *this;
|
||||
for (auto v : vars)
|
||||
r = m->mk_var(v) * r;
|
||||
return r;
|
||||
}
|
||||
|
||||
std::pair<unsigned_vector, pdd> pdd::var_factors() const {
|
||||
if (is_val())
|
||||
return { unsigned_vector(), *this };
|
||||
|
|
@ -1924,49 +1954,23 @@ namespace dd {
|
|||
return { unsigned_vector(), *this };
|
||||
|
||||
unsigned_vector lo_and_hi;
|
||||
auto merge = [&](unsigned_vector& lo_vars, unsigned_vector& hi_vars) {
|
||||
unsigned ir = 0, jr = 0;
|
||||
for (unsigned i = 0, j = 0; i < lo_vars.size() || j < hi_vars.size(); ) {
|
||||
if (i == lo_vars.size())
|
||||
hi_vars[jr++] = hi_vars[j++];
|
||||
else if (j == hi_vars.size())
|
||||
lo_vars[ir++] = lo_vars[i++];
|
||||
else if (lo_vars[i] == hi_vars[j]) {
|
||||
lo_and_hi.push_back(lo_vars[i]);
|
||||
++i;
|
||||
++j;
|
||||
}
|
||||
else if (m->m_var2level[lo_vars[i]] > m->m_var2level[hi_vars[j]])
|
||||
hi_vars[jr++] = hi_vars[j++];
|
||||
else
|
||||
lo_vars[ir++] = lo_vars[i++];
|
||||
}
|
||||
lo_vars.shrink(ir);
|
||||
hi_vars.shrink(jr);
|
||||
};
|
||||
|
||||
auto mul = [&](unsigned_vector const& vars, pdd p) {
|
||||
for (auto v : vars)
|
||||
p *= m->mk_var(v);
|
||||
return p;
|
||||
};
|
||||
|
||||
auto [hi_vars, p] = hi().var_factors();
|
||||
if (lo_vars.back() == v) {
|
||||
lo_vars.pop_back();
|
||||
merge(lo_vars, hi_vars);
|
||||
merge(lo_vars, hi_vars, lo_and_hi);
|
||||
lo_and_hi.push_back(v);
|
||||
return { lo_and_hi, mul(lo_vars, q) + mul(hi_vars, p) };
|
||||
return { lo_and_hi, q.mul(lo_vars) + p.mul(hi_vars) };
|
||||
}
|
||||
if (hi_vars.empty())
|
||||
return { unsigned_vector(), *this };
|
||||
|
||||
merge(lo_vars, hi_vars);
|
||||
merge(lo_vars, hi_vars, lo_and_hi);
|
||||
hi_vars.push_back(v);
|
||||
if (lo_and_hi.empty())
|
||||
return { unsigned_vector(), *this };
|
||||
else
|
||||
return { lo_and_hi, mul(lo_vars, q) + mul(hi_vars, p) };
|
||||
return { lo_and_hi, q.mul(lo_vars) + p.mul(hi_vars) };
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -483,6 +483,8 @@ namespace dd {
|
|||
* \brief factor out variables
|
||||
*/
|
||||
std::pair<unsigned_vector, pdd> var_factors() const;
|
||||
static void merge(unsigned_vector &lo, unsigned_vector &hi, unsigned_vector& common);
|
||||
pdd mul(unsigned_vector const &vars) const;
|
||||
|
||||
pdd subst_val0(vector<std::pair<unsigned, rational>> const& s) const { return m->subst_val0(*this, s); }
|
||||
pdd subst_val(pdd const& s) const { VERIFY_EQ(m, s.m); return m->subst_val(*this, s); }
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -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);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue