mirror of
https://github.com/Z3Prover/z3
synced 2025-07-03 03:15:41 +00:00
linear solver
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
17fcf79c04
commit
683ce27c8f
8 changed files with 264 additions and 42 deletions
|
@ -41,6 +41,33 @@ namespace polysat {
|
||||||
return alloc(ule_constraint, lvl, bvar, sign, a, b, d);
|
return alloc(ule_constraint, lvl, bvar, sign, a, b, d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// To do signed comparison of bitvectors, flip the msb and do unsigned comparison:
|
||||||
|
//
|
||||||
|
// x <=s y <=> x + 2^(w-1) <=u y + 2^(w-1)
|
||||||
|
//
|
||||||
|
// Example for bit width 3:
|
||||||
|
// 111 -1
|
||||||
|
// 110 -2
|
||||||
|
// 101 -3
|
||||||
|
// 100 -4
|
||||||
|
// 011 3
|
||||||
|
// 010 2
|
||||||
|
// 001 1
|
||||||
|
// 000 0
|
||||||
|
//
|
||||||
|
// Argument: flipping the msb swaps the negative and non-negative blocks
|
||||||
|
//
|
||||||
|
constraint* constraint::sle(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
|
||||||
|
auto shift = rational::power_of_two(a.power_of_2() - 1);
|
||||||
|
return ule(lvl, bvar, sign, a + shift, b + shift, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
constraint* constraint::slt(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
|
||||||
|
auto shift = rational::power_of_two(a.power_of_2() - 1);
|
||||||
|
return ult(lvl, bvar, sign, a + shift, b + shift, d);
|
||||||
|
}
|
||||||
|
|
||||||
constraint* constraint::ult(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
|
constraint* constraint::ult(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d) {
|
||||||
// a < b <=> !(b <= a)
|
// a < b <=> !(b <= a)
|
||||||
return ule(lvl, bvar, static_cast<csign_t>(!sign), b, a, d);
|
return ule(lvl, bvar, static_cast<csign_t>(!sign), b, a, d);
|
||||||
|
|
|
@ -17,7 +17,7 @@ Author:
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
enum ckind_t { eq_t, ule_t, sle_t, bit_t };
|
enum ckind_t { eq_t, ule_t, bit_t };
|
||||||
enum csign_t : bool { neg_t = false, pos_t = true };
|
enum csign_t : bool { neg_t = false, pos_t = true };
|
||||||
|
|
||||||
class eq_constraint;
|
class eq_constraint;
|
||||||
|
@ -42,10 +42,11 @@ namespace polysat {
|
||||||
static constraint* viable(unsigned lvl, bool_var bvar, csign_t sign, pvar v, bdd const& b, p_dependency_ref const& d);
|
static constraint* viable(unsigned lvl, bool_var bvar, csign_t sign, pvar v, bdd const& b, p_dependency_ref const& d);
|
||||||
static constraint* ule(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d);
|
static constraint* ule(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d);
|
||||||
static constraint* ult(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d);
|
static constraint* ult(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d);
|
||||||
|
static constraint* sle(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d);
|
||||||
|
static constraint* slt(unsigned lvl, bool_var bvar, csign_t sign, pdd const& a, pdd const& b, p_dependency_ref const& d);
|
||||||
virtual ~constraint() {}
|
virtual ~constraint() {}
|
||||||
bool is_eq() const { return m_kind == ckind_t::eq_t; }
|
bool is_eq() const { return m_kind == ckind_t::eq_t; }
|
||||||
bool is_ule() const { return m_kind == ckind_t::ule_t; }
|
bool is_ule() const { return m_kind == ckind_t::ule_t; }
|
||||||
bool is_sle() const { return m_kind == ckind_t::sle_t; }
|
|
||||||
ckind_t kind() const { return m_kind; }
|
ckind_t kind() const { return m_kind; }
|
||||||
virtual std::ostream& display(std::ostream& out) const = 0;
|
virtual std::ostream& display(std::ostream& out) const = 0;
|
||||||
bool propagate(solver& s, pvar v);
|
bool propagate(solver& s, pvar v);
|
||||||
|
|
|
@ -23,6 +23,7 @@ Author:
|
||||||
#include "math/interval/mod_interval.h"
|
#include "math/interval/mod_interval.h"
|
||||||
#include "util/heap.h"
|
#include "util/heap.h"
|
||||||
#include "util/map.h"
|
#include "util/map.h"
|
||||||
|
#include "util/rational.h"
|
||||||
#include "util/lbool.h"
|
#include "util/lbool.h"
|
||||||
#include "util/uint_set.h"
|
#include "util/uint_set.h"
|
||||||
|
|
||||||
|
@ -30,7 +31,15 @@ namespace polysat {
|
||||||
|
|
||||||
typedef unsigned var_t;
|
typedef unsigned var_t;
|
||||||
|
|
||||||
struct fixplex_base {};
|
struct fixplex_base {
|
||||||
|
virtual lbool make_feasible() = 0;
|
||||||
|
virtual void add_row(var_t base, unsigned num_vars, var_t const* vars, rational const* coeffs) = 0;
|
||||||
|
virtual void del_row(var_t base_var) = 0;
|
||||||
|
virtual std::ostream& display(std::ostream& out) const = 0;
|
||||||
|
virtual void collect_statistics(::statistics & st) const = 0;
|
||||||
|
virtual void set_bounds(var_t v, rational const& lo, rational const& hi) = 0;
|
||||||
|
virtual void restore_bound() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
|
@ -100,6 +109,13 @@ namespace polysat {
|
||||||
numeral m_base_coeff;
|
numeral m_base_coeff;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct stashed_bound : mod_interval<numeral> {
|
||||||
|
var_t m_var;
|
||||||
|
stashed_bound(var_t v, numeral const& lo, numeral const& hi):
|
||||||
|
mod_interval<numeral>(lo, hi),
|
||||||
|
m_var(v)
|
||||||
|
{}
|
||||||
|
};
|
||||||
|
|
||||||
struct fix_entry {
|
struct fix_entry {
|
||||||
var_t x;
|
var_t x;
|
||||||
|
@ -125,6 +141,7 @@ namespace polysat {
|
||||||
unsigned m_infeasible_var { null_var };
|
unsigned m_infeasible_var { null_var };
|
||||||
unsigned_vector m_base_vars;
|
unsigned_vector m_base_vars;
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
|
vector<stashed_bound> m_stashed_bounds;
|
||||||
map<numeral, fix_entry, typename manager::hash, typename manager::eq> m_value2fixed_var;
|
map<numeral, fix_entry, typename manager::hash, typename manager::eq> m_value2fixed_var;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -135,10 +152,18 @@ namespace polysat {
|
||||||
|
|
||||||
~fixplex();
|
~fixplex();
|
||||||
|
|
||||||
|
lbool make_feasible() override;
|
||||||
|
void add_row(var_t base, unsigned num_vars, var_t const* vars, rational const* coeffs) override;
|
||||||
|
std::ostream& display(std::ostream& out) const override;
|
||||||
|
void collect_statistics(::statistics & st) const override;
|
||||||
|
void del_row(var_t base_var) override;
|
||||||
|
void set_bounds(var_t v, rational const& lo, rational const& hi) override;
|
||||||
|
void restore_bound() override;
|
||||||
|
|
||||||
void set_bounds(var_t v, numeral const& lo, numeral const& hi);
|
void set_bounds(var_t v, numeral const& lo, numeral const& hi);
|
||||||
void unset_bounds(var_t v) { m_vars[v].set_free(); }
|
void unset_bounds(var_t v) { m_vars[v].set_free(); }
|
||||||
|
|
||||||
|
|
||||||
numeral const& lo(var_t var) const { return m_vars[var].lo; }
|
numeral const& lo(var_t var) const { return m_vars[var].lo; }
|
||||||
numeral const& hi(var_t var) const { return m_vars[var].hi; }
|
numeral const& hi(var_t var) const { return m_vars[var].hi; }
|
||||||
numeral const& value(var_t var) const { return m_vars[var].m_value; }
|
numeral const& value(var_t var) const { return m_vars[var].m_value; }
|
||||||
|
@ -149,12 +174,9 @@ namespace polysat {
|
||||||
void propagate_eqs();
|
void propagate_eqs();
|
||||||
vector<var_eq> const& var_eqs() const { return m_var_eqs; }
|
vector<var_eq> const& var_eqs() const { return m_var_eqs; }
|
||||||
void reset_eqs() { m_var_eqs.reset(); }
|
void reset_eqs() { m_var_eqs.reset(); }
|
||||||
lbool make_feasible();
|
|
||||||
void add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs);
|
void add_row(var_t base, unsigned num_vars, var_t const* vars, numeral const* coeffs);
|
||||||
std::ostream& display(std::ostream& out) const;
|
|
||||||
void collect_statistics(::statistics & st) const;
|
|
||||||
row get_infeasible_row();
|
row get_infeasible_row();
|
||||||
void del_row(var_t base_var);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
|
@ -244,6 +266,7 @@ namespace polysat {
|
||||||
return a == b;
|
return a == b;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
numeral from_rational(rational const& n) { return n.get_uint64(); }
|
||||||
void reset() {}
|
void reset() {}
|
||||||
void reset(numeral& n) { n = 0; }
|
void reset(numeral& n) { n = 0; }
|
||||||
void del(numeral const& n) {}
|
void del(numeral const& n) {}
|
||||||
|
|
|
@ -83,6 +83,14 @@ namespace polysat {
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
void fixplex<Ext>::add_row(var_t base_var, unsigned num_vars, var_t const* vars, rational const* coeffs) {
|
||||||
|
vector<numeral> _coeffs;
|
||||||
|
for (unsigned i = 0; i < num_vars; ++i)
|
||||||
|
_coeffs.push_back(m.from_rational(coeffs[i]));
|
||||||
|
add_row(base_var, num_vars, vars, _coeffs.data());
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void fixplex<Ext>::add_row(var_t base_var, unsigned num_vars, var_t const* vars, numeral const* coeffs) {
|
void fixplex<Ext>::add_row(var_t base_var, unsigned num_vars, var_t const* vars, numeral const* coeffs) {
|
||||||
for (unsigned i = 0; i < num_vars; ++i)
|
for (unsigned i = 0; i < num_vars; ++i)
|
||||||
|
@ -442,6 +450,21 @@ namespace polysat {
|
||||||
update_value(v, value2delta(v, value(v)));
|
update_value(v, value2delta(v, value(v)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
void fixplex<Ext>::set_bounds(var_t v, rational const& _lo, rational const& _hi) {
|
||||||
|
numeral lo = m.from_rational(_lo);
|
||||||
|
numeral hi = m.from_rational(_hi);
|
||||||
|
m_stashed_bounds.push_back(stashed_bound(v, lo, hi));
|
||||||
|
set_bounds(v, lo, hi);
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
void fixplex<Ext>::restore_bound() {
|
||||||
|
auto const& b = m_stashed_bounds.back();
|
||||||
|
set_bounds(b.m_var, b.lo, b.hi);
|
||||||
|
m_stashed_bounds.pop_back();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check if the coefficient b of y has the minimal number of trailing zeros.
|
* Check if the coefficient b of y has the minimal number of trailing zeros.
|
||||||
* In other words, the coefficient b is a multiple of the smallest power of 2.
|
* In other words, the coefficient b is a multiple of the smallest power of 2.
|
||||||
|
|
|
@ -17,19 +17,155 @@ Author:
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
void linear_solver::push() {}
|
void linear_solver::push() {
|
||||||
void linear_solver::pop(unsigned n) {}
|
m_trail.push_back(trail_i::inc_level_i);
|
||||||
void linear_solver::new_constraint(constraint& c) {}
|
}
|
||||||
void linear_solver::set_value(pvar v, rational const& value) {}
|
|
||||||
void linear_solver::set_bound(pvar v, rational const& lo, rational const& hi) {}
|
void linear_solver::pop(unsigned n) {
|
||||||
void linear_solver::activate_constraint(constraint& c) {}
|
while (n > 0) {
|
||||||
|
switch (m_trail.back()) {
|
||||||
|
case trail_i::inc_level_i:
|
||||||
|
--n;
|
||||||
|
break;
|
||||||
|
case trail_i::add_var_i:
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
break;
|
||||||
|
case trail_i::set_bound_i: {
|
||||||
|
auto [v, sz] = m_rows.back();
|
||||||
|
sz2fixplex(sz).restore_bound();
|
||||||
|
m_rows.pop_back();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case trail_i::set_value_i:
|
||||||
|
break;
|
||||||
|
case trail_i::add_row_i: {
|
||||||
|
auto [v, sz] = m_rows.back();
|
||||||
|
sz2fixplex(sz).del_row(v);
|
||||||
|
m_rows.pop_back();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case trail_i::activate_constraint_i:
|
||||||
|
// not needed?
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
m_trail.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fixplex_base& linear_solver::sz2fixplex(unsigned sz) {
|
||||||
|
fixplex_base* b = m_fix.get(sz, nullptr);
|
||||||
|
if (!b) {
|
||||||
|
switch (sz) {
|
||||||
|
case 64:
|
||||||
|
b = alloc(fixplex<uint64_ext>, s.m_lim);
|
||||||
|
break;
|
||||||
|
case 8:
|
||||||
|
case 16:
|
||||||
|
case 32:
|
||||||
|
case 128:
|
||||||
|
case 256:
|
||||||
|
default:
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
m_fix.set(sz, b);
|
||||||
|
}
|
||||||
|
return *b;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linear_solver::new_constraint(constraint& c) {
|
||||||
|
switch (c.kind()) {
|
||||||
|
case ckind_t::eq_t: {
|
||||||
|
//
|
||||||
|
// create the row c.p() - v == 0
|
||||||
|
// when equality is asserted, set range on v as v == 0 or v > 0.
|
||||||
|
//
|
||||||
|
pdd p = c.to_eq().p();
|
||||||
|
unsigned sz = p.power_of_2();
|
||||||
|
linearize(p);
|
||||||
|
var_t v = fresh_var(sz);
|
||||||
|
m_vars.push_back(v);
|
||||||
|
m_coeffs.push_back(rational::power_of_two(sz) - 1);
|
||||||
|
sz2fixplex(sz).add_row(v, m_vars.size(), m_vars.data(), m_coeffs.data());
|
||||||
|
m_rows.push_back(std::make_pair(v, sz));
|
||||||
|
m_trail.push_back(trail_i::add_row_i);
|
||||||
|
m_bool_var2row.setx(c.bvar(), v, UINT_MAX);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ckind_t::ule_t:
|
||||||
|
case ckind_t::bit_t:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void linear_solver::activate_constraint(constraint& c) {
|
||||||
|
switch (c.kind()) {
|
||||||
|
case ckind_t::eq_t: {
|
||||||
|
var_t v = m_bool_var2row[c.bvar()];
|
||||||
|
pdd p = c.to_eq().p();
|
||||||
|
unsigned sz = p.power_of_2();
|
||||||
|
auto& fp = sz2fixplex(sz);
|
||||||
|
|
||||||
|
m_trail.push_back(trail_i::set_bound_i);
|
||||||
|
m_rows.push_back(std::make_pair(v, sz));
|
||||||
|
if (c.is_positive())
|
||||||
|
fp.set_bounds(v, rational::zero(), rational::zero());
|
||||||
|
else
|
||||||
|
fp.set_bounds(v, rational::one(), rational::power_of_two(sz) - 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case ckind_t::ule_t:
|
||||||
|
case ckind_t::bit_t:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void linear_solver::linearize(pdd const& p) {
|
||||||
|
unsigned sz = p.power_of_2();
|
||||||
|
m_vars.reset();
|
||||||
|
m_coeffs.reset();
|
||||||
|
for (auto const& m : p) {
|
||||||
|
m_vars.push_back(mono2var(sz, m.vars));
|
||||||
|
m_coeffs.push_back(m.coeff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var_t linear_solver::mono2var(unsigned sz, unsigned_vector const& var) {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
var_t linear_solver::fresh_var(unsigned sz) {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linear_solver::set_value(pvar v, rational const& value) {
|
||||||
|
}
|
||||||
|
|
||||||
|
void linear_solver::set_bound(pvar v, rational const& lo, rational const& hi) {
|
||||||
|
unsigned sz = s.size(v);
|
||||||
|
auto& fp = sz2fixplex(sz);
|
||||||
|
m_trail.push_back(trail_i::set_bound_i);
|
||||||
|
m_rows.push_back(std::make_pair(v, sz));
|
||||||
|
fp.set_bounds(v, lo, hi);
|
||||||
|
}
|
||||||
|
|
||||||
// check integer modular feasibility under current bounds.
|
// check integer modular feasibility under current bounds.
|
||||||
lbool linear_solver::check() { return l_undef; }
|
lbool linear_solver::check() {
|
||||||
void linear_solver::unsat_core(unsigned_vector& deps) {}
|
return l_undef;
|
||||||
|
}
|
||||||
|
|
||||||
|
void linear_solver::unsat_core(unsigned_vector& deps) {
|
||||||
|
}
|
||||||
|
|
||||||
// current value assigned to (linear) variable according to tableau.
|
// current value assigned to (linear) variable according to tableau.
|
||||||
rational linear_solver::value(pvar v) { return rational(0); }
|
rational linear_solver::value(pvar v) {
|
||||||
|
return rational(0);
|
||||||
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -35,11 +35,34 @@ namespace polysat {
|
||||||
class solver;
|
class solver;
|
||||||
|
|
||||||
class linear_solver {
|
class linear_solver {
|
||||||
|
enum trail_i {
|
||||||
|
inc_level_i,
|
||||||
|
add_var_i,
|
||||||
|
set_bound_i,
|
||||||
|
set_value_i,
|
||||||
|
add_row_i,
|
||||||
|
activate_constraint_i
|
||||||
|
};
|
||||||
|
|
||||||
solver& s;
|
solver& s;
|
||||||
ptr_vector<fixplex_base> m_fix;
|
scoped_ptr_vector<fixplex_base> m_fix;
|
||||||
|
svector<trail_i> m_trail;
|
||||||
|
svector<std::pair<var_t, unsigned>> m_rows;
|
||||||
unsigned_vector m_var2ext;
|
unsigned_vector m_var2ext;
|
||||||
unsigned_vector m_ext2var;
|
unsigned_vector m_ext2var;
|
||||||
|
|
||||||
|
svector<var_t> m_vars;
|
||||||
|
vector<rational> m_coeffs;
|
||||||
|
svector<var_t> m_bool_var2row;
|
||||||
|
|
||||||
|
fixplex_base& sz2fixplex(unsigned sz);
|
||||||
|
|
||||||
|
void linearize(pdd const& p);
|
||||||
|
var_t fresh_var(unsigned sz);
|
||||||
|
|
||||||
|
// bind monomial to variable.
|
||||||
|
var_t mono2var(unsigned sz, unsigned_vector const& m);
|
||||||
|
unsigned_vector var2mono(unsigned sz, var_t v) { throw default_exception("nyi"); }
|
||||||
//
|
//
|
||||||
// TBD trail object for
|
// TBD trail object for
|
||||||
// removing variables
|
// removing variables
|
||||||
|
|
|
@ -153,13 +153,14 @@ namespace polysat {
|
||||||
m_free_vars.del_var_eh(v);
|
m_free_vars.del_var_eh(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::new_constraint(constraint* c) {
|
bool_var solver::new_constraint(constraint* c) {
|
||||||
SASSERT(c);
|
SASSERT(c);
|
||||||
LOG("New constraint: " << *c);
|
LOG("New constraint: " << *c);
|
||||||
m_linear_solver.new_constraint(*c);
|
m_linear_solver.new_constraint(*c);
|
||||||
m_constraints.push_back(c);
|
m_constraints.push_back(c);
|
||||||
SASSERT(!get_bv2c(c->bvar()));
|
SASSERT(!get_bv2c(c->bvar()));
|
||||||
insert_bv2c(c->bvar(), c);
|
insert_bv2c(c->bvar(), c);
|
||||||
|
return c->bvar();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_var solver::new_eq(pdd const& p, unsigned dep) {
|
bool_var solver::new_eq(pdd const& p, unsigned dep) {
|
||||||
|
@ -184,35 +185,17 @@ namespace polysat {
|
||||||
auto non_zero = sz2bits(sz).non_zero();
|
auto non_zero = sz2bits(sz).non_zero();
|
||||||
p_dependency_ref d(mk_dep(dep), m_dm);
|
p_dependency_ref d(mk_dep(dep), m_dm);
|
||||||
constraint* c = constraint::viable(m_level, m_next_bvar++, pos_t, slack, non_zero, d);
|
constraint* c = constraint::viable(m_level, m_next_bvar++, pos_t, slack, non_zero, d);
|
||||||
new_constraint(c);
|
return new_constraint(c);
|
||||||
return c->bvar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_var solver::new_ule(pdd const& p, pdd const& q, unsigned dep, csign_t sign) {
|
bool_var solver::new_ule(pdd const& p, pdd const& q, unsigned dep, csign_t sign) {
|
||||||
p_dependency_ref d(mk_dep(dep), m_dm);
|
p_dependency_ref d(mk_dep(dep), m_dm);
|
||||||
constraint* c = constraint::ule(m_level, m_next_bvar++, sign, p, q, d);
|
return new_constraint(constraint::ule(m_level, m_next_bvar++, sign, p, q, d));
|
||||||
new_constraint(c);
|
|
||||||
return c->bvar();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_var solver::new_sle(pdd const& p, pdd const& q, unsigned dep, csign_t sign) {
|
bool_var solver::new_sle(pdd const& p, pdd const& q, unsigned dep, csign_t sign) {
|
||||||
// To do signed comparison of bitvectors, flip the msb and do unsigned comparison:
|
p_dependency_ref d(mk_dep(dep), m_dm);
|
||||||
//
|
return new_constraint(constraint::sle(m_level, m_next_bvar++, sign, p, q, d));
|
||||||
// x <=s y <=> x + 2^(w-1) <=u y + 2^(w-1)
|
|
||||||
//
|
|
||||||
// Example for bit width 3:
|
|
||||||
// 111 -1
|
|
||||||
// 110 -2
|
|
||||||
// 101 -3
|
|
||||||
// 100 -4
|
|
||||||
// 011 3
|
|
||||||
// 010 2
|
|
||||||
// 001 1
|
|
||||||
// 000 0
|
|
||||||
//
|
|
||||||
// Argument: flipping the msb swaps the negative and non-negative blocks
|
|
||||||
auto shift = rational::power_of_two(p.power_of_2() - 1);
|
|
||||||
return new_ule(p + shift, q + shift, dep, sign);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool_var solver::new_ult(pdd const& p, pdd const& q, unsigned dep) {
|
bool_var solver::new_ult(pdd const& p, pdd const& q, unsigned dep) {
|
||||||
|
@ -257,6 +240,11 @@ namespace polysat {
|
||||||
push_qhead();
|
push_qhead();
|
||||||
while (can_propagate())
|
while (can_propagate())
|
||||||
propagate(m_search[m_qhead++].first);
|
propagate(m_search[m_qhead++].first);
|
||||||
|
|
||||||
|
linear_propagate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void solver::linear_propagate() {
|
||||||
switch (m_linear_solver.check()) {
|
switch (m_linear_solver.check()) {
|
||||||
case l_false:
|
case l_false:
|
||||||
// TODO extract conflict
|
// TODO extract conflict
|
||||||
|
|
|
@ -211,6 +211,7 @@ namespace polysat {
|
||||||
void decide(pvar v);
|
void decide(pvar v);
|
||||||
|
|
||||||
void narrow(pvar v);
|
void narrow(pvar v);
|
||||||
|
void linear_propagate();
|
||||||
|
|
||||||
p_dependency* mk_dep(unsigned dep) { return dep == null_dependency ? nullptr : m_dm.mk_leaf(dep); }
|
p_dependency* mk_dep(unsigned dep) { return dep == null_dependency ? nullptr : m_dm.mk_leaf(dep); }
|
||||||
|
|
||||||
|
@ -226,7 +227,7 @@ namespace polysat {
|
||||||
void backjump(unsigned new_level);
|
void backjump(unsigned new_level);
|
||||||
void add_lemma(constraint* c);
|
void add_lemma(constraint* c);
|
||||||
|
|
||||||
void new_constraint(constraint* c);
|
bool_var new_constraint(constraint* c);
|
||||||
|
|
||||||
bool invariant();
|
bool invariant();
|
||||||
bool invariant(scoped_ptr_vector<constraint> const& cs);
|
bool invariant(scoped_ptr_vector<constraint> const& cs);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue