mirror of
https://github.com/Z3Prover/z3
synced 2025-06-06 22:23:22 +00:00
compute with deps
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
40027df32f
commit
481e20bc20
6 changed files with 166 additions and 99 deletions
|
@ -317,6 +317,7 @@ static inline void bn_sqr_u32(uint32_t aLen, uint32_t *a, uint32_t *res)
|
||||||
res[i0 + i0] = r;
|
res[i0 + i0] = r;
|
||||||
}
|
}
|
||||||
uint32_t c0 = Hacl_Bignum_Addition_bn_add_eq_len_u32(resLen, res, res, res);
|
uint32_t c0 = Hacl_Bignum_Addition_bn_add_eq_len_u32(resLen, res, res, res);
|
||||||
|
(void)c0;
|
||||||
KRML_CHECK_SIZE(sizeof (uint32_t), resLen);
|
KRML_CHECK_SIZE(sizeof (uint32_t), resLen);
|
||||||
uint32_t *tmp = alloca(resLen * sizeof (uint32_t));
|
uint32_t *tmp = alloca(resLen * sizeof (uint32_t));
|
||||||
memset(tmp, 0U, resLen * sizeof (uint32_t));
|
memset(tmp, 0U, resLen * sizeof (uint32_t));
|
||||||
|
@ -329,6 +330,7 @@ static inline void bn_sqr_u32(uint32_t aLen, uint32_t *a, uint32_t *res)
|
||||||
tmp[(uint32_t)2U * i + (uint32_t)1U] = hi;
|
tmp[(uint32_t)2U * i + (uint32_t)1U] = hi;
|
||||||
}
|
}
|
||||||
uint32_t c1 = Hacl_Bignum_Addition_bn_add_eq_len_u32(resLen, res, tmp, res);
|
uint32_t c1 = Hacl_Bignum_Addition_bn_add_eq_len_u32(resLen, res, tmp, res);
|
||||||
|
(void)c1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void bn_sqr_u64(uint32_t aLen, uint64_t *a, uint64_t *res)
|
static inline void bn_sqr_u64(uint32_t aLen, uint64_t *a, uint64_t *res)
|
||||||
|
@ -366,6 +368,7 @@ static inline void bn_sqr_u64(uint32_t aLen, uint64_t *a, uint64_t *res)
|
||||||
res[i0 + i0] = r;
|
res[i0 + i0] = r;
|
||||||
}
|
}
|
||||||
uint64_t c0 = Hacl_Bignum_Addition_bn_add_eq_len_u64(resLen, res, res, res);
|
uint64_t c0 = Hacl_Bignum_Addition_bn_add_eq_len_u64(resLen, res, res, res);
|
||||||
|
(void)c0;
|
||||||
KRML_CHECK_SIZE(sizeof (uint64_t), resLen);
|
KRML_CHECK_SIZE(sizeof (uint64_t), resLen);
|
||||||
uint64_t *tmp = alloca(resLen * sizeof (uint64_t));
|
uint64_t *tmp = alloca(resLen * sizeof (uint64_t));
|
||||||
memset(tmp, 0U, resLen * sizeof (uint64_t));
|
memset(tmp, 0U, resLen * sizeof (uint64_t));
|
||||||
|
@ -378,6 +381,7 @@ static inline void bn_sqr_u64(uint32_t aLen, uint64_t *a, uint64_t *res)
|
||||||
tmp[(uint32_t)2U * i + (uint32_t)1U] = hi;
|
tmp[(uint32_t)2U * i + (uint32_t)1U] = hi;
|
||||||
}
|
}
|
||||||
uint64_t c1 = Hacl_Bignum_Addition_bn_add_eq_len_u64(resLen, res, tmp, res);
|
uint64_t c1 = Hacl_Bignum_Addition_bn_add_eq_len_u64(resLen, res, tmp, res);
|
||||||
|
(void)c1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -720,6 +724,7 @@ Hacl_Bignum_Karatsuba_bn_karatsuba_sqr_uint64(
|
||||||
uint64_t *tmp_ = tmp + aLen;
|
uint64_t *tmp_ = tmp + aLen;
|
||||||
uint64_t c0 = Hacl_Bignum_Addition_bn_sub_eq_len_u64(len2, a0, a1, tmp_);
|
uint64_t c0 = Hacl_Bignum_Addition_bn_sub_eq_len_u64(len2, a0, a1, tmp_);
|
||||||
uint64_t c1 = Hacl_Bignum_Addition_bn_sub_eq_len_u64(len2, a1, a0, t0);
|
uint64_t c1 = Hacl_Bignum_Addition_bn_sub_eq_len_u64(len2, a1, a0, t0);
|
||||||
|
(void)c1;
|
||||||
for (uint32_t i = (uint32_t)0U; i < len2; i++)
|
for (uint32_t i = (uint32_t)0U; i < len2; i++)
|
||||||
{
|
{
|
||||||
uint64_t *os = t0;
|
uint64_t *os = t0;
|
||||||
|
@ -727,6 +732,7 @@ Hacl_Bignum_Karatsuba_bn_karatsuba_sqr_uint64(
|
||||||
os[i] = x;
|
os[i] = x;
|
||||||
}
|
}
|
||||||
uint64_t c00 = c0;
|
uint64_t c00 = c0;
|
||||||
|
(void)c00;
|
||||||
uint64_t *t23 = tmp + aLen;
|
uint64_t *t23 = tmp + aLen;
|
||||||
uint64_t *tmp1 = tmp + aLen + aLen;
|
uint64_t *tmp1 = tmp + aLen + aLen;
|
||||||
Hacl_Bignum_Karatsuba_bn_karatsuba_sqr_uint64(len2, t0, tmp1, t23);
|
Hacl_Bignum_Karatsuba_bn_karatsuba_sqr_uint64(len2, t0, tmp1, t23);
|
||||||
|
@ -1428,6 +1434,7 @@ bn_almost_mont_reduction_u32(
|
||||||
uint32_t *tmp = alloca(len * sizeof (uint32_t));
|
uint32_t *tmp = alloca(len * sizeof (uint32_t));
|
||||||
memset(tmp, 0U, len * sizeof (uint32_t));
|
memset(tmp, 0U, len * sizeof (uint32_t));
|
||||||
uint32_t c1 = Hacl_Bignum_Addition_bn_sub_eq_len_u32(len, res, n, tmp);
|
uint32_t c1 = Hacl_Bignum_Addition_bn_sub_eq_len_u32(len, res, n, tmp);
|
||||||
|
(void)c1;
|
||||||
uint32_t m = (uint32_t)0U - c00;
|
uint32_t m = (uint32_t)0U - c00;
|
||||||
for (uint32_t i = (uint32_t)0U; i < len; i++)
|
for (uint32_t i = (uint32_t)0U; i < len; i++)
|
||||||
{
|
{
|
||||||
|
@ -1524,6 +1531,7 @@ bn_almost_mont_reduction_u64(
|
||||||
uint64_t *tmp = alloca(len * sizeof (uint64_t));
|
uint64_t *tmp = alloca(len * sizeof (uint64_t));
|
||||||
memset(tmp, 0U, len * sizeof (uint64_t));
|
memset(tmp, 0U, len * sizeof (uint64_t));
|
||||||
uint64_t c1 = Hacl_Bignum_Addition_bn_sub_eq_len_u64(len, res, n, tmp);
|
uint64_t c1 = Hacl_Bignum_Addition_bn_sub_eq_len_u64(len, res, n, tmp);
|
||||||
|
(void)c1;
|
||||||
uint64_t m = (uint64_t)0U - c00;
|
uint64_t m = (uint64_t)0U - c00;
|
||||||
for (uint32_t i = (uint32_t)0U; i < len; i++)
|
for (uint32_t i = (uint32_t)0U; i < len; i++)
|
||||||
{
|
{
|
||||||
|
|
|
@ -513,6 +513,7 @@ static inline void amont_sqr(uint64_t *n, uint64_t nInv_u64, uint64_t *aM, uint6
|
||||||
tmp[(uint32_t)2U * i + (uint32_t)1U] = hi;
|
tmp[(uint32_t)2U * i + (uint32_t)1U] = hi;
|
||||||
}
|
}
|
||||||
uint64_t c1 = Hacl_Bignum_Addition_bn_add_eq_len_u64(resLen, c, tmp, c);
|
uint64_t c1 = Hacl_Bignum_Addition_bn_add_eq_len_u64(resLen, c, tmp, c);
|
||||||
|
(void)c1;
|
||||||
areduction(n, nInv_u64, c, resM);
|
areduction(n, nInv_u64, c, resM);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -559,6 +560,7 @@ bn_slow_precomp(uint64_t *n, uint64_t mu, uint64_t *r2, uint64_t *a, uint64_t *r
|
||||||
uint64_t c00 = c0;
|
uint64_t c00 = c0;
|
||||||
uint64_t tmp[4U] = { 0U };
|
uint64_t tmp[4U] = { 0U };
|
||||||
uint64_t c1 = Hacl_Bignum256_sub(a_mod, n, tmp);
|
uint64_t c1 = Hacl_Bignum256_sub(a_mod, n, tmp);
|
||||||
|
(void)c1;
|
||||||
uint64_t m = (uint64_t)0U - c00;
|
uint64_t m = (uint64_t)0U - c00;
|
||||||
for (uint32_t i = (uint32_t)0U; i < (uint32_t)4U; i++)
|
for (uint32_t i = (uint32_t)0U; i < (uint32_t)4U; i++)
|
||||||
{
|
{
|
||||||
|
@ -1132,6 +1134,7 @@ bool Hacl_Bignum256_mod_inv_prime_vartime(uint64_t *n, uint64_t *a, uint64_t *re
|
||||||
uint64_t n2[4U] = { 0U };
|
uint64_t n2[4U] = { 0U };
|
||||||
uint64_t c0 = Lib_IntTypes_Intrinsics_sub_borrow_u64((uint64_t)0U, n[0U], (uint64_t)2U, n2);
|
uint64_t c0 = Lib_IntTypes_Intrinsics_sub_borrow_u64((uint64_t)0U, n[0U], (uint64_t)2U, n2);
|
||||||
uint64_t c1;
|
uint64_t c1;
|
||||||
|
(void)c1;
|
||||||
if ((uint32_t)1U < (uint32_t)4U)
|
if ((uint32_t)1U < (uint32_t)4U)
|
||||||
{
|
{
|
||||||
uint32_t rLen = (uint32_t)3U;
|
uint32_t rLen = (uint32_t)3U;
|
||||||
|
@ -1334,6 +1337,7 @@ Hacl_Bignum256_mod_inv_prime_vartime_precomp(
|
||||||
uint64_t n2[4U] = { 0U };
|
uint64_t n2[4U] = { 0U };
|
||||||
uint64_t c0 = Lib_IntTypes_Intrinsics_sub_borrow_u64((uint64_t)0U, k1.n[0U], (uint64_t)2U, n2);
|
uint64_t c0 = Lib_IntTypes_Intrinsics_sub_borrow_u64((uint64_t)0U, k1.n[0U], (uint64_t)2U, n2);
|
||||||
uint64_t c1;
|
uint64_t c1;
|
||||||
|
(void)c1;
|
||||||
if ((uint32_t)1U < (uint32_t)4U)
|
if ((uint32_t)1U < (uint32_t)4U)
|
||||||
{
|
{
|
||||||
uint32_t rLen = (uint32_t)3U;
|
uint32_t rLen = (uint32_t)3U;
|
||||||
|
|
|
@ -30,6 +30,8 @@ Author:
|
||||||
#include "util/ref.h"
|
#include "util/ref.h"
|
||||||
|
|
||||||
inline rational to_rational(uint64_t n) { return rational(n, rational::ui64()); }
|
inline rational to_rational(uint64_t n) { return rational(n, rational::ui64()); }
|
||||||
|
inline unsigned trailing_zeros(unsigned short n) { return trailing_zeros((uint32_t)n); }
|
||||||
|
inline unsigned trailing_zeros(unsigned char n) { return trailing_zeros((uint32_t)n); }
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
|
||||||
|
@ -40,6 +42,8 @@ namespace polysat {
|
||||||
virtual lbool make_feasible() = 0;
|
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 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 void del_row(var_t base_var) = 0;
|
||||||
|
virtual void push() = 0;
|
||||||
|
virtual void pop(unsigned n) = 0;
|
||||||
virtual std::ostream& display(std::ostream& out) const = 0;
|
virtual std::ostream& display(std::ostream& out) const = 0;
|
||||||
virtual void collect_statistics(::statistics & st) const = 0;
|
virtual void collect_statistics(::statistics & st) const = 0;
|
||||||
virtual void set_bounds(var_t v, rational const& lo, rational const& hi, unsigned dep) = 0;
|
virtual void set_bounds(var_t v, rational const& lo, rational const& hi, unsigned dep) = 0;
|
||||||
|
@ -50,6 +54,7 @@ namespace polysat {
|
||||||
virtual void add_lt(var_t v, var_t w, unsigned dep) = 0;
|
virtual void add_lt(var_t v, var_t w, unsigned dep) = 0;
|
||||||
virtual void restore_ineq() = 0;
|
virtual void restore_ineq() = 0;
|
||||||
virtual unsigned_vector const& get_unsat_core() const = 0;
|
virtual unsigned_vector const& get_unsat_core() const = 0;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
@ -95,14 +100,6 @@ namespace polysat {
|
||||||
S_DEFAULT
|
S_DEFAULT
|
||||||
};
|
};
|
||||||
|
|
||||||
#if 0
|
|
||||||
struct dep_config {
|
|
||||||
static const bool ref_count = true;
|
|
||||||
typedef unsigned value;
|
|
||||||
};
|
|
||||||
typedef dependency_manager<dep_config> dep_manager;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
struct var_info : public mod_interval<numeral> {
|
struct var_info : public mod_interval<numeral> {
|
||||||
unsigned m_base2row:29;
|
unsigned m_base2row:29;
|
||||||
unsigned m_is_base:1;
|
unsigned m_is_base:1;
|
||||||
|
@ -156,6 +153,13 @@ namespace polysat {
|
||||||
v(v), w(w), strict(s), dep(dep) {}
|
v(v), w(w), strict(s), dep(dep) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum trail_i {
|
||||||
|
inc_level_i,
|
||||||
|
set_bound_i,
|
||||||
|
add_ineq_i,
|
||||||
|
add_row_i
|
||||||
|
};
|
||||||
|
|
||||||
static const var_t null_var = UINT_MAX;
|
static const var_t null_var = UINT_MAX;
|
||||||
reslimit& m_limit;
|
reslimit& m_limit;
|
||||||
mutable manager m;
|
mutable manager m;
|
||||||
|
@ -175,6 +179,8 @@ namespace polysat {
|
||||||
stats m_stats;
|
stats m_stats;
|
||||||
vector<stashed_bound> m_stashed_bounds;
|
vector<stashed_bound> m_stashed_bounds;
|
||||||
u_dependency_manager m_deps;
|
u_dependency_manager m_deps;
|
||||||
|
svector<trail_i> m_trail;
|
||||||
|
svector<var_t> m_row_trail;
|
||||||
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;
|
||||||
|
|
||||||
// inequalities
|
// inequalities
|
||||||
|
@ -192,6 +198,9 @@ namespace polysat {
|
||||||
|
|
||||||
~fixplex() override;
|
~fixplex() override;
|
||||||
|
|
||||||
|
void push() override;
|
||||||
|
void pop(unsigned n) override;
|
||||||
|
|
||||||
lbool make_feasible() override;
|
lbool make_feasible() override;
|
||||||
void add_row(var_t base, unsigned num_vars, var_t const* vars, rational const* coeffs) 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;
|
std::ostream& display(std::ostream& out) const override;
|
||||||
|
@ -206,6 +215,7 @@ namespace polysat {
|
||||||
virtual void restore_ineq() override;
|
virtual void restore_ineq() override;
|
||||||
|
|
||||||
void set_bounds(var_t v, numeral const& lo, numeral const& hi, unsigned dep);
|
void set_bounds(var_t v, numeral const& lo, numeral const& hi, unsigned dep);
|
||||||
|
void update_bounds(var_t v, numeral const& l, numeral const& h, u_dependency* dep);
|
||||||
void unset_bounds(var_t v) { m_vars[v].set_free(); }
|
void unset_bounds(var_t v) { m_vars[v].set_free(); }
|
||||||
|
|
||||||
|
|
||||||
|
@ -244,8 +254,11 @@ namespace polysat {
|
||||||
lbool propagate_bounds(row const& r);
|
lbool propagate_bounds(row const& r);
|
||||||
lbool propagate_bounds(ineq const& i);
|
lbool propagate_bounds(ineq const& i);
|
||||||
lbool new_bound(row const& r, var_t x, mod_interval<numeral> const& range);
|
lbool new_bound(row const& r, var_t x, mod_interval<numeral> const& range);
|
||||||
lbool new_bound(ineq const& i, var_t x, numeral const& lo, numeral const& hi);
|
lbool new_bound(ineq const& i, var_t x, numeral const& lo, numeral const& hi, u_dependency* a = nullptr, u_dependency* b = nullptr);
|
||||||
lbool conflict_bound(ineq const& i);
|
lbool conflict(ineq const& i, u_dependency* a = nullptr, u_dependency* b = nullptr);
|
||||||
|
lbool conflict(u_dependency* a);
|
||||||
|
lbool conflict(u_dependency* a, u_dependency* b) { return conflict(m_deps.mk_join(a, b)); }
|
||||||
|
u_dependency* row2dep(row const& r);
|
||||||
void pivot(var_t x_i, var_t x_j, numeral const& b, numeral const& value);
|
void pivot(var_t x_i, var_t x_j, numeral const& b, numeral const& value);
|
||||||
numeral value2delta(var_t v, numeral const& new_value) const;
|
numeral value2delta(var_t v, numeral const& new_value) const;
|
||||||
numeral value2error(var_t v, numeral const& new_value) const;
|
numeral value2error(var_t v, numeral const& new_value) const;
|
||||||
|
@ -279,6 +292,8 @@ namespace polysat {
|
||||||
void set_infeasible_base(var_t v);
|
void set_infeasible_base(var_t v);
|
||||||
void set_infeasible_bounds(var_t v);
|
void set_infeasible_bounds(var_t v);
|
||||||
|
|
||||||
|
u_dependency* mk_leaf(unsigned dep) { return UINT_MAX == dep ? nullptr : m_deps.mk_leaf(dep); }
|
||||||
|
|
||||||
// facilities for handling inequalities
|
// facilities for handling inequalities
|
||||||
void add_ineq(var_t v, var_t w, unsigned dep, bool strict);
|
void add_ineq(var_t v, var_t w, unsigned dep, bool strict);
|
||||||
void touch_var(var_t x);
|
void touch_var(var_t x);
|
||||||
|
|
|
@ -72,6 +72,37 @@ namespace polysat {
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
void fixplex<Ext>::push() {
|
||||||
|
m_trail.push_back(trail_i::inc_level_i);
|
||||||
|
m_deps.push_scope();
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
void fixplex<Ext>::pop(unsigned n) {
|
||||||
|
m_deps.pop_scope(n);
|
||||||
|
while (n > 0) {
|
||||||
|
switch (m_trail.back()) {
|
||||||
|
case trail_i::inc_level_i:
|
||||||
|
--n;
|
||||||
|
break;
|
||||||
|
case trail_i::set_bound_i:
|
||||||
|
restore_bound();
|
||||||
|
break;
|
||||||
|
case trail_i::add_row_i:
|
||||||
|
del_row(m_row_trail.back());
|
||||||
|
m_row_trail.pop_back();
|
||||||
|
break;
|
||||||
|
case trail_i::add_ineq_i:
|
||||||
|
restore_ineq();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
|
m_trail.pop_back();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void fixplex<Ext>::ensure_var(var_t v) {
|
void fixplex<Ext>::ensure_var(var_t v) {
|
||||||
while (v >= m_vars.size()) {
|
while (v >= m_vars.size()) {
|
||||||
|
@ -173,6 +204,8 @@ namespace polysat {
|
||||||
++m_stats.m_num_approx;
|
++m_stats.m_num_approx;
|
||||||
SASSERT(well_formed_row(r));
|
SASSERT(well_formed_row(r));
|
||||||
SASSERT(well_formed());
|
SASSERT(well_formed());
|
||||||
|
m_trail.push_back(trail_i::add_row_i);
|
||||||
|
m_row_trail.push_back(base_var);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
|
@ -486,13 +519,7 @@ namespace polysat {
|
||||||
*/
|
*/
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void fixplex<Ext>::set_bounds(var_t v, numeral const& l, numeral const& h, unsigned dep) {
|
void fixplex<Ext>::set_bounds(var_t v, numeral const& l, numeral const& h, unsigned dep) {
|
||||||
auto lo0 = m_vars[v].lo;
|
update_bounds(v, l, h, mk_leaf(dep));
|
||||||
auto hi0 = m_vars[v].hi;
|
|
||||||
m_vars[v] &= mod_interval(l, h);
|
|
||||||
if (lo0 != m_vars[v].lo)
|
|
||||||
m_vars[v].m_lo_dep = nullptr; // TODO set_atom(dep);
|
|
||||||
if (hi0 != m_vars[v].hi)
|
|
||||||
m_vars[v].m_hi_dep = nullptr; // TODO .set_atom(dep);
|
|
||||||
if (in_bounds(v))
|
if (in_bounds(v))
|
||||||
return;
|
return;
|
||||||
if (is_base(v))
|
if (is_base(v))
|
||||||
|
@ -501,18 +528,29 @@ namespace polysat {
|
||||||
update_value(v, value2delta(v, value(v)));
|
update_value(v, value2delta(v, value(v)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
void fixplex<Ext>::update_bounds(var_t v, numeral const& l, numeral const& h, u_dependency* dep) {
|
||||||
|
auto lo0 = m_vars[v].lo;
|
||||||
|
auto hi0 = m_vars[v].hi;
|
||||||
|
m_stashed_bounds.push_back(stashed_bound(v, m_vars[v]));
|
||||||
|
m_trail.push_back(trail_i::set_bound_i);
|
||||||
|
m_vars[v] &= mod_interval(l, h);
|
||||||
|
if (lo0 != m_vars[v].lo)
|
||||||
|
m_vars[v].m_lo_dep = dep;
|
||||||
|
if (hi0 != m_vars[v].hi)
|
||||||
|
m_vars[v].m_hi_dep = dep;
|
||||||
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void fixplex<Ext>::set_bounds(var_t v, rational const& _lo, rational const& _hi, unsigned dep) {
|
void fixplex<Ext>::set_bounds(var_t v, rational const& _lo, rational const& _hi, unsigned dep) {
|
||||||
numeral lo = m.from_rational(_lo);
|
numeral lo = m.from_rational(_lo);
|
||||||
numeral hi = m.from_rational(_hi);
|
numeral hi = m.from_rational(_hi);
|
||||||
m_stashed_bounds.push_back(stashed_bound(v, m_vars[v]));
|
|
||||||
set_bounds(v, lo, hi, dep);
|
set_bounds(v, lo, hi, dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void fixplex<Ext>::set_value(var_t v, rational const& _val, unsigned dep) {
|
void fixplex<Ext>::set_value(var_t v, rational const& _val, unsigned dep) {
|
||||||
numeral val = m.from_rational(_val);
|
numeral val = m.from_rational(_val);
|
||||||
m_stashed_bounds.push_back(stashed_bound(v, m_vars[v]));
|
|
||||||
set_bounds(v, val, val + 1, dep);
|
set_bounds(v, val, val + 1, dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -524,14 +562,10 @@ namespace polysat {
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
void fixplex<Ext>::restore_bound() {
|
void fixplex<Ext>::restore_bound() {
|
||||||
auto& b = m_stashed_bounds.back();
|
auto& b = m_stashed_bounds.back();
|
||||||
auto* lo = m_vars[b.m_var].m_lo_dep;
|
|
||||||
auto* hi = m_vars[b.m_var].m_hi_dep;
|
|
||||||
m_vars[b.m_var].lo = b.lo;
|
m_vars[b.m_var].lo = b.lo;
|
||||||
m_vars[b.m_var].hi = b.hi;
|
m_vars[b.m_var].hi = b.hi;
|
||||||
m_vars[b.m_var].m_lo_dep = b.m_lo_dep;
|
m_vars[b.m_var].m_lo_dep = b.m_lo_dep;
|
||||||
m_vars[b.m_var].m_hi_dep = b.m_hi_dep;
|
m_vars[b.m_var].m_hi_dep = b.m_hi_dep;
|
||||||
// m_deps.dec_ref(lo);
|
|
||||||
// m_deps.dec_ref(hi);
|
|
||||||
m_stashed_bounds.pop_back();
|
m_stashed_bounds.pop_back();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -542,6 +576,7 @@ namespace polysat {
|
||||||
m_var2ineqs[v].push_back(idx);
|
m_var2ineqs[v].push_back(idx);
|
||||||
m_var2ineqs[w].push_back(idx);
|
m_var2ineqs[w].push_back(idx);
|
||||||
m_ineqs_to_check.push_back(idx);
|
m_ineqs_to_check.push_back(idx);
|
||||||
|
m_trail.push_back(trail_i::add_ineq_i);
|
||||||
m_ineqs.push_back(ineq(v, w, dep, strict));
|
m_ineqs.push_back(ineq(v, w, dep, strict));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1126,50 +1161,64 @@ namespace polysat {
|
||||||
var_t v = i.v, w = i.w;
|
var_t v = i.v, w = i.w;
|
||||||
bool s = i.strict;
|
bool s = i.strict;
|
||||||
if (s && lo(v) + 1 == 0)
|
if (s && lo(v) + 1 == 0)
|
||||||
return conflict_bound(i);
|
return conflict(i, m_vars[v].m_lo_dep);
|
||||||
else if (s && hi(w) == 0)
|
else if (s && hi(w) == 0)
|
||||||
return conflict_bound(i);
|
return conflict(i, m_vars[v].m_hi_dep);
|
||||||
else if (s && lo(v) >= hi(w))
|
else if (s && lo(v) >= hi(w))
|
||||||
return conflict_bound(i);
|
return conflict(i, m_vars[v].m_lo_dep, m_vars[w].m_hi_dep);
|
||||||
else if (!s && lo(v) > hi(w))
|
else if (!s && lo(v) > hi(w))
|
||||||
return conflict_bound(i);
|
return conflict(i, m_vars[v].m_lo_dep, m_vars[w].m_hi_dep);
|
||||||
else if (s && hi(v) >= hi(w)) {
|
else if (s && hi(v) >= hi(w)) {
|
||||||
SASSERT(lo(v) < hi(w));
|
SASSERT(lo(v) < hi(w));
|
||||||
SASSERT(hi(w) != 0);
|
SASSERT(hi(w) != 0);
|
||||||
return new_bound(i, v, lo(v), hi(w) - 1);
|
return new_bound(i, v, lo(v), hi(w) - 1, m_vars[v].m_hi_dep, m_vars[w].m_hi_dep);
|
||||||
}
|
}
|
||||||
else if (s && lo(v) >= lo(w)) {
|
else if (s && lo(v) >= lo(w)) {
|
||||||
SASSERT(lo(v) + 1 != 0);
|
SASSERT(lo(v) + 1 != 0);
|
||||||
SASSERT(hi(w) > lo(v));
|
SASSERT(hi(w) > lo(v));
|
||||||
return new_bound(i, w, lo(v) + 1, hi(w));
|
return new_bound(i, w, lo(v) + 1, hi(w), m_vars[v].m_lo_dep, m_vars[w].m_lo_dep);
|
||||||
}
|
}
|
||||||
else if (!s && hi(v) > hi(w)) {
|
else if (!s && hi(v) > hi(w)) {
|
||||||
SASSERT(lo(v) <= hi(w));
|
SASSERT(lo(v) <= hi(w));
|
||||||
return new_bound(i, v, lo(v), hi(w));
|
return new_bound(i, v, lo(v), hi(w), m_vars[v].m_hi_dep, m_vars[w].m_hi_dep);
|
||||||
}
|
}
|
||||||
else if (!s && lo(v) > lo(w)) {
|
else if (!s && lo(v) > lo(w)) {
|
||||||
SASSERT(lo(v) <= hi(w));
|
SASSERT(lo(v) <= hi(w));
|
||||||
return new_bound(i, w, lo(v), hi(w));
|
return new_bound(i, w, lo(v), hi(w), m_vars[v].m_lo_dep, m_vars[w].m_lo_dep);
|
||||||
}
|
}
|
||||||
return l_true;
|
return l_true;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
lbool fixplex<Ext>::conflict_bound(ineq const& i) {
|
lbool fixplex<Ext>::conflict(ineq const& i, u_dependency* a, u_dependency* b) {
|
||||||
NOT_IMPLEMENTED_YET();
|
return conflict(a, m_deps.mk_join(mk_leaf(i.dep), b));
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
lbool fixplex<Ext>::conflict(u_dependency* a) {
|
||||||
|
m_unsat_core.reset();
|
||||||
|
m_deps.linearize(a, m_unsat_core);
|
||||||
return l_false;
|
return l_false;
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Ext>
|
template<typename Ext>
|
||||||
lbool fixplex<Ext>::new_bound(ineq const& i, var_t x, numeral const& l, numeral const& h) {
|
u_dependency* fixplex<Ext>::row2dep(row const& r) {
|
||||||
mod_interval<numeral> r(l, h);
|
u_dependency* d = nullptr;
|
||||||
bool was_fixed = lo(x) + 1 == hi(x);
|
for (auto const& e : M.row_entries(r)) {
|
||||||
m_vars[x] &= r;
|
var_t v = e.var();
|
||||||
if (m_vars[x].is_empty()) {
|
d = m_deps.mk_join(m_vars[v].m_lo_dep, d);
|
||||||
// TODO
|
d = m_deps.mk_join(m_vars[v].m_hi_dep, d);
|
||||||
IF_VERBOSE(0, verbose_stream() << "infeasible\n");
|
|
||||||
return l_false;
|
|
||||||
}
|
}
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename Ext>
|
||||||
|
lbool fixplex<Ext>::new_bound(ineq const& i, var_t x, numeral const& l, numeral const& h, u_dependency* a, u_dependency* b) {
|
||||||
|
bool was_fixed = lo(x) + 1 == hi(x);
|
||||||
|
u_dependency* dep = m_deps.mk_join(mk_leaf(i.dep), m_deps.mk_join(a, b));
|
||||||
|
update_bounds(x, l, h, dep);
|
||||||
|
if (m_vars[x].is_empty())
|
||||||
|
return conflict(m_vars[x].m_lo_dep, m_vars[x].m_hi_dep);
|
||||||
else if (!was_fixed && lo(x) + 1 == hi(x)) {
|
else if (!was_fixed && lo(x) + 1 == hi(x)) {
|
||||||
// TBD: track based on inequality not row
|
// TBD: track based on inequality not row
|
||||||
// fixed_var_eh(r, x);
|
// fixed_var_eh(r, x);
|
||||||
|
@ -1182,12 +1231,10 @@ namespace polysat {
|
||||||
if (range.is_free())
|
if (range.is_free())
|
||||||
return l_true;
|
return l_true;
|
||||||
bool was_fixed = lo(x) + 1 == hi(x);
|
bool was_fixed = lo(x) + 1 == hi(x);
|
||||||
m_vars[x] &= range;
|
update_bounds(x, range.lo, range.hi, row2dep(r));
|
||||||
IF_VERBOSE(0, verbose_stream() << "new-bound v" << x << " " << m_vars[x] << "\n");
|
IF_VERBOSE(0, verbose_stream() << "new-bound v" << x << " " << m_vars[x] << "\n");
|
||||||
if (m_vars[x].is_empty()) {
|
if (m_vars[x].is_empty())
|
||||||
IF_VERBOSE(0, verbose_stream() << "infeasible\n");
|
return conflict(m_vars[x].m_lo_dep, m_vars[x].m_hi_dep);
|
||||||
return l_false;
|
|
||||||
}
|
|
||||||
else if (!was_fixed && lo(x) + 1 == hi(x))
|
else if (!was_fixed && lo(x) + 1 == hi(x))
|
||||||
fixed_var_eh(r, x);
|
fixed_var_eh(r, x);
|
||||||
return l_true;
|
return l_true;
|
||||||
|
|
|
@ -22,9 +22,13 @@ namespace polysat {
|
||||||
|
|
||||||
void linear_solver::push() {
|
void linear_solver::push() {
|
||||||
m_trail.push_back(trail_i::inc_level_i);
|
m_trail.push_back(trail_i::inc_level_i);
|
||||||
|
for (auto* f : m_fix_ptr)
|
||||||
|
f->push();
|
||||||
}
|
}
|
||||||
|
|
||||||
void linear_solver::pop(unsigned n) {
|
void linear_solver::pop(unsigned n) {
|
||||||
|
for (auto* f : m_fix_ptr)
|
||||||
|
f->pop(n);
|
||||||
while (n > 0) {
|
while (n > 0) {
|
||||||
switch (m_trail.back()) {
|
switch (m_trail.back()) {
|
||||||
case trail_i::inc_level_i:
|
case trail_i::inc_level_i:
|
||||||
|
@ -43,24 +47,6 @@ namespace polysat {
|
||||||
m_monomials.pop_back();
|
m_monomials.pop_back();
|
||||||
break;
|
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::add_row_i: {
|
|
||||||
auto [v, sz] = m_rows.back();
|
|
||||||
sz2fixplex(sz).del_row(v);
|
|
||||||
m_rows.pop_back();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case trail_i::add_ineq_i: {
|
|
||||||
auto [v, sz] = m_rows.back();
|
|
||||||
sz2fixplex(sz).restore_ineq();
|
|
||||||
m_rows.pop_back();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case trail_i::set_active_i:
|
case trail_i::set_active_i:
|
||||||
m_active.pop_back();
|
m_active.pop_back();
|
||||||
break;
|
break;
|
||||||
|
@ -73,10 +59,16 @@ namespace polysat {
|
||||||
m_unsat_f = nullptr;
|
m_unsat_f = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
fixplex_base& linear_solver::sz2fixplex(unsigned sz) {
|
fixplex_base* linear_solver::sz2fixplex(unsigned sz) {
|
||||||
fixplex_base* b = m_fix.get(sz, nullptr);
|
fixplex_base* b = m_fix.get(sz, nullptr);
|
||||||
if (!b) {
|
if (!b) {
|
||||||
switch (sz) {
|
switch (sz) {
|
||||||
|
case 8:
|
||||||
|
b = alloc(fixplex<generic_uint_ext<unsigned char>>, s.m_lim);
|
||||||
|
break;
|
||||||
|
case 16:
|
||||||
|
b = alloc(fixplex<generic_uint_ext<unsigned short>>, s.m_lim);
|
||||||
|
break;
|
||||||
case 32:
|
case 32:
|
||||||
b = alloc(fixplex<generic_uint_ext<unsigned>>, s.m_lim);
|
b = alloc(fixplex<generic_uint_ext<unsigned>>, s.m_lim);
|
||||||
break;
|
break;
|
||||||
|
@ -93,9 +85,11 @@ namespace polysat {
|
||||||
NOT_IMPLEMENTED_YET();
|
NOT_IMPLEMENTED_YET();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (b)
|
||||||
|
m_fix_ptr.push_back(b);
|
||||||
m_fix.set(sz, b);
|
m_fix.set(sz, b);
|
||||||
}
|
}
|
||||||
return *b;
|
return b;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -107,9 +101,9 @@ namespace polysat {
|
||||||
var_t v = fresh_var(sz);
|
var_t v = fresh_var(sz);
|
||||||
m_vars.push_back(v);
|
m_vars.push_back(v);
|
||||||
m_coeffs.push_back(rational::power_of_two(sz) - 1);
|
m_coeffs.push_back(rational::power_of_two(sz) - 1);
|
||||||
sz2fixplex(sz).add_row(v, m_vars.size(), m_vars.data(), m_coeffs.data());
|
auto* f = sz2fixplex(sz);
|
||||||
m_rows.push_back(std::make_pair(v, sz));
|
if (f)
|
||||||
m_trail.push_back(trail_i::add_row_i);
|
f->add_row(v, m_vars.size(), m_vars.data(), m_coeffs.data());
|
||||||
return v;
|
return v;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,15 +129,15 @@ namespace polysat {
|
||||||
unsigned c_dep = constraint_idx2dep(m_active.size() - 1);
|
unsigned c_dep = constraint_idx2dep(m_active.size() - 1);
|
||||||
var_t v = m_bool_var2row[c.bvar()].first;
|
var_t v = m_bool_var2row[c.bvar()].first;
|
||||||
unsigned sz = c.p().power_of_2();
|
unsigned sz = c.p().power_of_2();
|
||||||
auto& fp = sz2fixplex(sz);
|
auto* fp = sz2fixplex(sz);
|
||||||
m_trail.push_back(trail_i::set_bound_i);
|
if (!fp)
|
||||||
m_rows.push_back(std::make_pair(v, sz));
|
return;
|
||||||
rational z(0), o(1);
|
rational z(0), o(1);
|
||||||
SASSERT(!c.is_undef());
|
SASSERT(!c.is_undef());
|
||||||
if (is_positive)
|
if (is_positive)
|
||||||
fp.set_bounds(v, z, z, c_dep);
|
fp->set_bounds(v, z, z, c_dep);
|
||||||
else
|
else
|
||||||
fp.set_bounds(v, o, z, c_dep);
|
fp->set_bounds(v, o, z, c_dep);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
|
@ -162,44 +156,40 @@ namespace polysat {
|
||||||
void linear_solver::assert_le(bool is_positive, ule_constraint& c) {
|
void linear_solver::assert_le(bool is_positive, ule_constraint& c) {
|
||||||
auto [v, w] = m_bool_var2row[c.bvar()];
|
auto [v, w] = m_bool_var2row[c.bvar()];
|
||||||
unsigned sz = c.lhs().power_of_2();
|
unsigned sz = c.lhs().power_of_2();
|
||||||
auto& fp = sz2fixplex(sz);
|
auto* fp = sz2fixplex(sz);
|
||||||
|
if (!fp)
|
||||||
|
return;
|
||||||
unsigned c_dep = constraint_idx2dep(m_active.size() - 1);
|
unsigned c_dep = constraint_idx2dep(m_active.size() - 1);
|
||||||
rational z(0);
|
rational z(0);
|
||||||
if (c.rhs().is_val()) {
|
if (c.rhs().is_val()) {
|
||||||
bool is_max_value = false;
|
bool is_max_value = false;
|
||||||
if (is_positive)
|
if (is_positive)
|
||||||
// v <= rhs
|
// v <= rhs
|
||||||
fp.set_bounds(v, z, c.rhs().val(), c_dep);
|
fp->set_bounds(v, z, c.rhs().val(), c_dep);
|
||||||
else if (is_max_value)
|
else if (is_max_value)
|
||||||
throw default_exception("conflict not implemented");
|
throw default_exception("conflict not implemented");
|
||||||
else
|
else
|
||||||
// rhs < v
|
// rhs < v
|
||||||
fp.set_bounds(v, c.rhs().val() + 1, z, c_dep);
|
fp->set_bounds(v, c.rhs().val() + 1, z, c_dep);
|
||||||
m_trail.push_back(trail_i::set_bound_i);
|
|
||||||
m_rows.push_back(std::make_pair(v, sz));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c.lhs().is_val()) {
|
if (c.lhs().is_val()) {
|
||||||
if (is_positive)
|
if (is_positive)
|
||||||
// w >= lhs
|
// w >= lhs
|
||||||
fp.set_bounds(w, c.lhs().val(), z, c_dep);
|
fp->set_bounds(w, c.lhs().val(), z, c_dep);
|
||||||
else if (c.lhs().val() == 0)
|
else if (c.lhs().val() == 0)
|
||||||
throw default_exception("conflict not implemented");
|
throw default_exception("conflict not implemented");
|
||||||
else
|
else
|
||||||
// w < lhs
|
// w < lhs
|
||||||
fp.set_bounds(w, z, c.lhs().val() - 1, c_dep);
|
fp->set_bounds(w, z, c.lhs().val() - 1, c_dep);
|
||||||
m_trail.push_back(trail_i::set_bound_i);
|
|
||||||
m_rows.push_back(std::make_pair(w, sz));
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (is_positive)
|
if (is_positive)
|
||||||
fp.add_le(v, w, c_dep);
|
fp->add_le(v, w, c_dep);
|
||||||
else
|
else
|
||||||
fp.add_lt(w, v, c_dep);
|
fp->add_lt(w, v, c_dep);
|
||||||
m_trail.push_back(trail_i::add_ineq_i);
|
|
||||||
m_rows.push_back(std::make_pair(v, sz));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -273,20 +263,20 @@ namespace polysat {
|
||||||
|
|
||||||
void linear_solver::set_value(pvar v, rational const& value, unsigned dep) {
|
void linear_solver::set_value(pvar v, rational const& value, unsigned dep) {
|
||||||
unsigned sz = s.size(v);
|
unsigned sz = s.size(v);
|
||||||
auto& fp = sz2fixplex(sz);
|
auto* fp = sz2fixplex(sz);
|
||||||
|
if (!fp)
|
||||||
|
return;
|
||||||
var_t w = pvar2var(sz, v);
|
var_t w = pvar2var(sz, v);
|
||||||
m_trail.push_back(trail_i::set_bound_i);
|
fp->set_value(w, value, external_dep2dep(dep));
|
||||||
m_rows.push_back(std::make_pair(w, sz));
|
|
||||||
fp.set_value(w, value, external_dep2dep(dep));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void linear_solver::set_bound(pvar v, rational const& lo, rational const& hi, unsigned dep) {
|
void linear_solver::set_bound(pvar v, rational const& lo, rational const& hi, unsigned dep) {
|
||||||
unsigned sz = s.size(v);
|
unsigned sz = s.size(v);
|
||||||
auto& fp = sz2fixplex(sz);
|
auto* fp = sz2fixplex(sz);
|
||||||
|
if (!fp)
|
||||||
|
return;
|
||||||
var_t w = pvar2var(sz, v);
|
var_t w = pvar2var(sz, v);
|
||||||
m_trail.push_back(trail_i::set_bound_i);
|
fp->set_bounds(w, lo, hi, external_dep2dep(dep));
|
||||||
m_rows.push_back(std::make_pair(w, sz));
|
|
||||||
fp.set_bounds(w, lo, hi, external_dep2dep(dep));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -325,7 +315,10 @@ namespace polysat {
|
||||||
// current value assigned to (linear) variable according to tableau.
|
// current value assigned to (linear) variable according to tableau.
|
||||||
rational linear_solver::value(pvar v) {
|
rational linear_solver::value(pvar v) {
|
||||||
unsigned sz = s.size(v);
|
unsigned sz = s.size(v);
|
||||||
return sz2fixplex(sz).get_value(pvar2var(sz, v));
|
auto* fp = sz2fixplex(sz);
|
||||||
|
if (!fp)
|
||||||
|
return rational::zero();
|
||||||
|
return fp->get_value(pvar2var(sz, v));
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
|
@ -41,7 +41,6 @@ namespace polysat {
|
||||||
inc_level_i,
|
inc_level_i,
|
||||||
add_var_i,
|
add_var_i,
|
||||||
add_mono_i,
|
add_mono_i,
|
||||||
set_bound_i,
|
|
||||||
add_ineq_i,
|
add_ineq_i,
|
||||||
add_row_i,
|
add_row_i,
|
||||||
set_active_i
|
set_active_i
|
||||||
|
@ -78,6 +77,7 @@ namespace polysat {
|
||||||
|
|
||||||
solver& s;
|
solver& s;
|
||||||
scoped_ptr_vector<fixplex_base> m_fix;
|
scoped_ptr_vector<fixplex_base> m_fix;
|
||||||
|
ptr_vector<fixplex_base> m_fix_ptr;
|
||||||
svector<trail_i> m_trail;
|
svector<trail_i> m_trail;
|
||||||
svector<std::pair<var_t, unsigned>> m_rows;
|
svector<std::pair<var_t, unsigned>> m_rows;
|
||||||
unsigned_vector m_var2ext;
|
unsigned_vector m_var2ext;
|
||||||
|
@ -94,7 +94,7 @@ namespace polysat {
|
||||||
svector<mono_info> m_monomials;
|
svector<mono_info> m_monomials;
|
||||||
fixplex_base* m_unsat_f = nullptr;
|
fixplex_base* m_unsat_f = nullptr;
|
||||||
|
|
||||||
fixplex_base& sz2fixplex(unsigned sz);
|
fixplex_base* sz2fixplex(unsigned sz);
|
||||||
|
|
||||||
void linearize(pdd const& p);
|
void linearize(pdd const& p);
|
||||||
var_t fresh_var(unsigned sz);
|
var_t fresh_var(unsigned sz);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue