mirror of
https://github.com/Z3Prover/z3
synced 2025-06-26 15:53:41 +00:00
redo fixed bits, add simplifications to intblast solver
This commit is contained in:
parent
c4b7061590
commit
30c0771d24
11 changed files with 127 additions and 121 deletions
|
@ -471,18 +471,25 @@ namespace intblast {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool solver::is_non_negative(expr* bv_expr, expr* e) {
|
||||||
|
auto N = rational::power_of_two(bv.get_bv_size(bv_expr));
|
||||||
|
rational r;
|
||||||
|
if (a.is_numeral(e, r))
|
||||||
|
return r >= 0;
|
||||||
|
if (is_bounded(e, N))
|
||||||
|
return true;
|
||||||
|
expr* x, * y;
|
||||||
|
if (a.is_mul(e, x, y))
|
||||||
|
return is_non_negative(bv_expr, x) && is_non_negative(bv_expr, y);
|
||||||
|
if (a.is_add(e, x, y))
|
||||||
|
return is_non_negative(bv_expr, x) && is_non_negative(bv_expr, y);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
expr* solver::umod(expr* bv_expr, unsigned i) {
|
expr* solver::umod(expr* bv_expr, unsigned i) {
|
||||||
expr* x = arg(i);
|
expr* x = arg(i);
|
||||||
rational r;
|
|
||||||
rational N = bv_size(bv_expr);
|
rational N = bv_size(bv_expr);
|
||||||
if (a.is_numeral(x, r)) {
|
return amod(bv_expr, x, N);
|
||||||
if (0 <= r && r < N)
|
|
||||||
return x;
|
|
||||||
return a.mk_int(mod(r, N));
|
|
||||||
}
|
|
||||||
if (is_bounded(x, N))
|
|
||||||
return x;
|
|
||||||
return a.mk_mod(x, a.mk_int(N));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
expr* solver::smod(expr* bv_expr, unsigned i) {
|
expr* solver::smod(expr* bv_expr, unsigned i) {
|
||||||
|
@ -492,7 +499,7 @@ namespace intblast {
|
||||||
rational r;
|
rational r;
|
||||||
if (a.is_numeral(x, r))
|
if (a.is_numeral(x, r))
|
||||||
return a.mk_int(mod(r + shift, N));
|
return a.mk_int(mod(r + shift, N));
|
||||||
return a.mk_mod(add(x, a.mk_int(shift)), a.mk_int(N));
|
return amod(bv_expr, add(x, a.mk_int(shift)), N);
|
||||||
}
|
}
|
||||||
|
|
||||||
expr_ref solver::mul(expr* x, expr* y) {
|
expr_ref solver::mul(expr* x, expr* y) {
|
||||||
|
@ -505,6 +512,9 @@ namespace intblast {
|
||||||
return _y;
|
return _y;
|
||||||
if (a.is_one(y))
|
if (a.is_one(y))
|
||||||
return _x;
|
return _x;
|
||||||
|
rational v1, v2;
|
||||||
|
if (a.is_numeral(x, v1) && a.is_numeral(y, v2))
|
||||||
|
return expr_ref(a.mk_int(v1 * v2), m);
|
||||||
_x = a.mk_mul(x, y);
|
_x = a.mk_mul(x, y);
|
||||||
return _x;
|
return _x;
|
||||||
}
|
}
|
||||||
|
@ -515,10 +525,37 @@ namespace intblast {
|
||||||
return _y;
|
return _y;
|
||||||
if (a.is_zero(y))
|
if (a.is_zero(y))
|
||||||
return _x;
|
return _x;
|
||||||
|
rational v1, v2;
|
||||||
|
if (a.is_numeral(x, v1) && a.is_numeral(y, v2))
|
||||||
|
return expr_ref(a.mk_int(v1 + v2), m);
|
||||||
_x = a.mk_add(x, y);
|
_x = a.mk_add(x, y);
|
||||||
return _x;
|
return _x;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Perform simplifications that are claimed sound when the bit-vector interpretations of
|
||||||
|
* mod/div always guard the mod and dividend to be non-zero.
|
||||||
|
* Potentially shady area is for arithmetic expressions created by int2bv.
|
||||||
|
* They will be guarded by a modulus which dose not disappear.
|
||||||
|
*/
|
||||||
|
expr* solver::amod(expr* bv_expr, expr* x, rational const& N) {
|
||||||
|
rational v;
|
||||||
|
expr* r, *c, * t, * e;
|
||||||
|
if (m.is_ite(x, c, t, e))
|
||||||
|
r = m.mk_ite(c, amod(bv_expr, t, N), amod(bv_expr, e, N));
|
||||||
|
else if (a.is_idiv(x, t, e) && a.is_numeral(t, v) && 0 <= v && v < N && is_non_negative(bv_expr, e))
|
||||||
|
r = x;
|
||||||
|
else if (a.is_mod(x, t, e) && a.is_numeral(t, v) && 0 <= v && v < N)
|
||||||
|
r = x;
|
||||||
|
else if (a.is_numeral(x, v))
|
||||||
|
r = a.mk_int(mod(v, N));
|
||||||
|
else if (is_bounded(x, N))
|
||||||
|
r = x;
|
||||||
|
else
|
||||||
|
r = a.mk_mod(x, a.mk_int(N));
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
||||||
rational solver::bv_size(expr* bv_expr) {
|
rational solver::bv_size(expr* bv_expr) {
|
||||||
return rational::power_of_two(bv.get_bv_size(bv_expr->get_sort()));
|
return rational::power_of_two(bv.get_bv_size(bv_expr->get_sort()));
|
||||||
}
|
}
|
||||||
|
@ -649,7 +686,7 @@ namespace intblast {
|
||||||
auto A = rational::power_of_two(sz - n);
|
auto A = rational::power_of_two(sz - n);
|
||||||
auto B = rational::power_of_two(n);
|
auto B = rational::power_of_two(n);
|
||||||
auto hi = mul(r, a.mk_int(A));
|
auto hi = mul(r, a.mk_int(A));
|
||||||
auto lo = a.mk_mod(a.mk_idiv(umod(e, 0), a.mk_int(B)), a.mk_int(A));
|
auto lo = amod(e, a.mk_idiv(umod(e, 0), a.mk_int(B)), A);
|
||||||
r = add(hi, lo);
|
r = add(hi, lo);
|
||||||
}
|
}
|
||||||
return r;
|
return r;
|
||||||
|
|
|
@ -74,8 +74,10 @@ namespace intblast {
|
||||||
expr* umod(expr* bv_expr, unsigned i);
|
expr* umod(expr* bv_expr, unsigned i);
|
||||||
expr* smod(expr* bv_expr, unsigned i);
|
expr* smod(expr* bv_expr, unsigned i);
|
||||||
bool is_bounded(expr* v, rational const& N);
|
bool is_bounded(expr* v, rational const& N);
|
||||||
|
bool is_non_negative(expr* bv_expr, expr* e);
|
||||||
expr_ref mul(expr* x, expr* y);
|
expr_ref mul(expr* x, expr* y);
|
||||||
expr_ref add(expr* x, expr* y);
|
expr_ref add(expr* x, expr* y);
|
||||||
|
expr* amod(expr* bv_expr, expr* x, rational const& N);
|
||||||
rational bv_size(expr* bv_expr);
|
rational bv_size(expr* bv_expr);
|
||||||
|
|
||||||
void translate_expr(expr* e);
|
void translate_expr(expr* e);
|
||||||
|
|
|
@ -20,96 +20,41 @@ namespace polysat {
|
||||||
void fixed_bits::reset() {
|
void fixed_bits::reset() {
|
||||||
m_fixed_slices.reset();
|
m_fixed_slices.reset();
|
||||||
m_var = null_var;
|
m_var = null_var;
|
||||||
m_fixed.reset();
|
|
||||||
m_bits.reset();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset with fixed bits information for variable v
|
// reset with fixed bits information for variable v
|
||||||
void fixed_bits::reset(pvar v) {
|
void fixed_bits::init(pvar v) {
|
||||||
m_fixed_slices.reset();
|
m_fixed_slices.reset();
|
||||||
m_var = v;
|
m_var = v;
|
||||||
m_fixed.reset();
|
c.get_fixed_bits(v, m_fixed_slices);
|
||||||
m_fixed.resize(c.size(v), l_undef);
|
|
||||||
m_bits.reserve(c.size(v));
|
|
||||||
fixed_bits_vector fbs;
|
|
||||||
c.get_fixed_bits(v, fbs);
|
|
||||||
for (auto const& fb : fbs)
|
|
||||||
for (unsigned i = fb.lo; i <= fb.hi; ++i)
|
|
||||||
m_fixed[i] = to_lbool(fb.value.get_bit(i - fb.lo));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// find then next value >= val that agrees with fixed bits, or false if none exists within the maximal value for val.
|
// if x[hi:lo] = value, then
|
||||||
// examples
|
// 2^(w-hi+1)* x >=
|
||||||
// fixed bits: 1?0 (least significant bit is last)
|
bool fixed_bits::check(rational const& val, fi_record& fi) {
|
||||||
// val: 101
|
for (auto const& s : m_fixed_slices) {
|
||||||
// next: 110
|
rational bw = rational::power_of_two(s.hi - s.lo + 1);
|
||||||
|
if (s.value != mod(machine_div2k(val, s.lo + 1), bw)) {
|
||||||
// fixed bits ?1?0
|
rational hi_val = s.value;
|
||||||
// val 1011
|
rational lo_val = mod(s.value + 1, bw);
|
||||||
// next 1100
|
unsigned sz = c.size(m_var);
|
||||||
|
pdd lo = c.value(rational::power_of_two(sz - s.hi - 1) * lo_val, c.size(m_var));
|
||||||
// algorithm: Let i be the most significant index where fixed bits disagree with val.
|
pdd hi = c.value(rational::power_of_two(sz - s.hi - 1) * hi_val, c.size(m_var));
|
||||||
// Set non-fixed values below i to 0.
|
fi.reset();
|
||||||
// If m_fixed[i] == l_true; then updating val to mask by fixed bits sufficies.
|
fi.interval = eval_interval::proper(lo, lo_val, hi, hi_val);
|
||||||
// Otherwise, the range above the disagreement has to be incremented.
|
fi.deps.push_back(dependency({ m_var, s }));
|
||||||
// Increment the non-fixed bits by 1
|
fi.bit_width = s.hi - s.lo + 1;
|
||||||
// The first non-fixed 0 position is set to 1, non-fixed positions below are set to 0.
|
fi.coeff = 1;
|
||||||
// If there are none, then the value is maximal and we return false.
|
|
||||||
|
|
||||||
bool fixed_bits::next(rational& val) {
|
|
||||||
if (m_fixed_slices.empty())
|
|
||||||
return true;
|
|
||||||
unsigned sz = c.size(m_var);
|
|
||||||
for (unsigned i = 0; i < sz; ++i)
|
|
||||||
m_bits[i] = val.get_bit(i);
|
|
||||||
unsigned i = sz;
|
|
||||||
for (; i-- > 0; )
|
|
||||||
if (m_fixed[i] != l_undef && m_fixed[i] != to_lbool(m_bits[i]))
|
|
||||||
break;
|
|
||||||
if (i == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
for (unsigned j = 0; j < sz; ++j) {
|
|
||||||
if (m_fixed[j] != l_undef)
|
|
||||||
m_bits[j] = m_fixed[j] == l_true;
|
|
||||||
else if (j < i)
|
|
||||||
m_bits[j] = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (m_fixed[i] == l_false) {
|
|
||||||
for (; i < sz; ++i) {
|
|
||||||
if (m_fixed[i] != l_undef)
|
|
||||||
continue;
|
|
||||||
if (m_bits[i])
|
|
||||||
m_bits[i] = false;
|
|
||||||
else {
|
|
||||||
m_bits[i] = true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
CTRACE("bv", i == sz, display(tout << "overflow\n"));
|
|
||||||
// overflow
|
|
||||||
if (i == sz)
|
|
||||||
return false;
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
val = 0;
|
|
||||||
for (unsigned i = sz; i-- > 0;)
|
|
||||||
val = val * 2 + rational(m_bits[i]);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// explain the fixed bits ranges.
|
|
||||||
dependency_vector fixed_bits::explain() {
|
|
||||||
dependency_vector result;
|
|
||||||
for (auto const& slice : m_fixed_slices)
|
|
||||||
result.push_back(dependency({ m_var, slice }));
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::ostream& fixed_bits::display(std::ostream& out) const {
|
std::ostream& fixed_bits::display(std::ostream& out) const {
|
||||||
return out << "fixed bits: v" << m_var << " " << m_fixed << "\n";
|
for (auto const& s : m_fixed_slices)
|
||||||
|
out << s.hi << " " << s.lo << " " << s.value << "\n";
|
||||||
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -13,6 +13,7 @@ Author:
|
||||||
#pragma once
|
#pragma once
|
||||||
#include "sat/smt/polysat/types.h"
|
#include "sat/smt/polysat/types.h"
|
||||||
#include "sat/smt/polysat/constraints.h"
|
#include "sat/smt/polysat/constraints.h"
|
||||||
|
#include "sat/smt/polysat/forbidden_intervals.h"
|
||||||
#include "util/vector.h"
|
#include "util/vector.h"
|
||||||
|
|
||||||
namespace polysat {
|
namespace polysat {
|
||||||
|
@ -31,9 +32,7 @@ namespace polysat {
|
||||||
class fixed_bits {
|
class fixed_bits {
|
||||||
core& c;
|
core& c;
|
||||||
pvar m_var = null_var;
|
pvar m_var = null_var;
|
||||||
vector<fixed_slice> m_fixed_slices;
|
fixed_bits_vector m_fixed_slices;
|
||||||
svector<lbool> m_fixed;
|
|
||||||
bool_vector m_bits;
|
|
||||||
public:
|
public:
|
||||||
fixed_bits(core& c) : c(c) {}
|
fixed_bits(core& c) : c(c) {}
|
||||||
|
|
||||||
|
@ -41,13 +40,9 @@ namespace polysat {
|
||||||
void reset();
|
void reset();
|
||||||
|
|
||||||
// reset with fixed bits information for variable v
|
// reset with fixed bits information for variable v
|
||||||
void reset(pvar v);
|
void init(pvar v);
|
||||||
|
|
||||||
// find then next value >= val that agrees with fixed bits, or false if none exists within the maximal value for val.
|
bool check(rational const& val, fi_record& fi);
|
||||||
bool next(rational& val);
|
|
||||||
|
|
||||||
// explain the fixed bits ranges.
|
|
||||||
dependency_vector explain();
|
|
||||||
|
|
||||||
std::ostream& display(std::ostream& out) const;
|
std::ostream& display(std::ostream& out) const;
|
||||||
};
|
};
|
||||||
|
|
|
@ -26,6 +26,7 @@ namespace polysat {
|
||||||
eval_interval interval;
|
eval_interval interval;
|
||||||
vector<signed_constraint> side_cond;
|
vector<signed_constraint> side_cond;
|
||||||
vector<signed_constraint> src; // only units may have multiple src (as they can consist of contracted bit constraints)
|
vector<signed_constraint> src; // only units may have multiple src (as they can consist of contracted bit constraints)
|
||||||
|
vector<dependency> deps;
|
||||||
rational coeff;
|
rational coeff;
|
||||||
unsigned bit_width = 0; // number of lower bits; TODO: should move this to viable::entry; where the coeff/bit-width is adapted accordingly
|
unsigned bit_width = 0; // number of lower bits; TODO: should move this to viable::entry; where the coeff/bit-width is adapted accordingly
|
||||||
|
|
||||||
|
@ -37,6 +38,7 @@ namespace polysat {
|
||||||
side_cond.reset();
|
side_cond.reset();
|
||||||
src.reset();
|
src.reset();
|
||||||
coeff.reset();
|
coeff.reset();
|
||||||
|
deps.reset();
|
||||||
bit_width = 0;
|
bit_width = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -116,7 +116,7 @@ namespace polysat {
|
||||||
return out << "v" << js.v << " at offset " << js.offset;
|
return out << "v" << js.v << " at offset " << js.offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
using fixed_bits_vector = svector<fixed_slice>;
|
using fixed_bits_vector = vector<fixed_slice>;
|
||||||
|
|
||||||
using dependency_vector = vector<dependency>;
|
using dependency_vector = vector<dependency>;
|
||||||
using constraint_or_dependency = std::variant<signed_constraint, dependency>;
|
using constraint_or_dependency = std::variant<signed_constraint, dependency>;
|
||||||
|
|
|
@ -87,7 +87,7 @@ namespace polysat {
|
||||||
m_explain.reset();
|
m_explain.reset();
|
||||||
m_var = v;
|
m_var = v;
|
||||||
m_num_bits = c.size(v);
|
m_num_bits = c.size(v);
|
||||||
m_fixed_bits.reset(v);
|
m_fixed_bits.init(v);
|
||||||
init_overlaps(v);
|
init_overlaps(v);
|
||||||
m_conflict = false;
|
m_conflict = false;
|
||||||
|
|
||||||
|
@ -101,8 +101,9 @@ namespace polysat {
|
||||||
return find_t::empty;
|
return find_t::empty;
|
||||||
|
|
||||||
if (!n) {
|
if (!n) {
|
||||||
if (refine_disequal_lin(v, lo) &&
|
if (check_fixed_bits(v, lo) &&
|
||||||
refine_equal_lin(v, lo))
|
check_disequal_lin(v, lo) &&
|
||||||
|
check_equal_lin(v, lo))
|
||||||
return find_t::multiple;
|
return find_t::multiple;
|
||||||
++rounds;
|
++rounds;
|
||||||
}
|
}
|
||||||
|
@ -128,11 +129,6 @@ namespace polysat {
|
||||||
//
|
//
|
||||||
|
|
||||||
viable::entry* viable::find_overlap(rational& val) {
|
viable::entry* viable::find_overlap(rational& val) {
|
||||||
// disable fixed-bits until added to explanation trail.
|
|
||||||
if (false && !m_fixed_bits.next(val)) {
|
|
||||||
val = 0;
|
|
||||||
VERIFY(m_fixed_bits.next(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
entry* last = nullptr;
|
entry* last = nullptr;
|
||||||
for (auto const& [w, offset] : m_overlaps) {
|
for (auto const& [w, offset] : m_overlaps) {
|
||||||
|
@ -217,7 +213,7 @@ namespace polysat {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool viable::refine_equal_lin(pvar v, rational const& val) {
|
bool viable::check_equal_lin(pvar v, rational const& val) {
|
||||||
// LOG_H2("refine-equal-lin with v" << v << ", val = " << val);
|
// LOG_H2("refine-equal-lin with v" << v << ", val = " << val);
|
||||||
entry const* e = m_equal_lin[v];
|
entry const* e = m_equal_lin[v];
|
||||||
if (!e)
|
if (!e)
|
||||||
|
@ -357,7 +353,22 @@ namespace polysat {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool viable::refine_disequal_lin(pvar v, rational const& val) {
|
bool viable::check_fixed_bits(pvar v, rational const& val) {
|
||||||
|
// disable fixed bits for now
|
||||||
|
return true;
|
||||||
|
|
||||||
|
auto e = alloc_entry(v, constraint_id::null());
|
||||||
|
if (m_fixed_bits.check(val, *e)) {
|
||||||
|
m_alloc.push_back(e);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
intersect(v, e);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool viable::check_disequal_lin(pvar v, rational const& val) {
|
||||||
// LOG_H2("refine-disequal-lin with v" << v << ", val = " << val);
|
// LOG_H2("refine-disequal-lin with v" << v << ", val = " << val);
|
||||||
entry const* e = m_diseq_lin[v];
|
entry const* e = m_diseq_lin[v];
|
||||||
if (!e)
|
if (!e)
|
||||||
|
@ -490,14 +501,13 @@ namespace polysat {
|
||||||
|
|
||||||
TRACE("bv", display_explain(tout));
|
TRACE("bv", display_explain(tout));
|
||||||
|
|
||||||
result.append(m_fixed_bits.explain());
|
|
||||||
|
|
||||||
if (last.e->interval.is_full()) {
|
if (last.e->interval.is_full()) {
|
||||||
if (m_var != last.e->var)
|
if (m_var != last.e->var)
|
||||||
result.push_back(offset_claim(m_var, { last.e->var, 0 }));
|
result.push_back(offset_claim(m_var, { last.e->var, 0 }));
|
||||||
for (auto const& sc : last.e->side_cond)
|
for (auto const& sc : last.e->side_cond)
|
||||||
result.push_back(c.propagate(sc, c.explain_weak_eval(sc)));
|
result.push_back(c.propagate(sc, c.explain_weak_eval(sc)));
|
||||||
result.push_back(c.get_dependency(last.e->constraint_index));
|
if (!last.e->constraint_index.is_null())
|
||||||
|
result.push_back(c.get_dependency(last.e->constraint_index));
|
||||||
SASSERT(m_explain.size() == 1);
|
SASSERT(m_explain.size() == 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -506,14 +516,17 @@ namespace polysat {
|
||||||
auto index = e.e->constraint_index;
|
auto index = e.e->constraint_index;
|
||||||
explain_overlap(e, after, result);
|
explain_overlap(e, after, result);
|
||||||
after = e;
|
after = e;
|
||||||
if (seen.contains(index.id))
|
if (!index.is_null() && seen.contains(index.id))
|
||||||
continue;
|
continue;
|
||||||
seen.insert(index.id);
|
if (!index.is_null())
|
||||||
|
seen.insert(index.id);
|
||||||
if (m_var != e.e->var)
|
if (m_var != e.e->var)
|
||||||
result.push_back(offset_claim(m_var, { e.e->var, 0 }));
|
result.push_back(offset_claim(m_var, { e.e->var, 0 }));
|
||||||
for (auto const& sc : e.e->side_cond)
|
for (auto const& sc : e.e->side_cond)
|
||||||
result.push_back(c.propagate(sc, c.explain_weak_eval(sc)));
|
result.push_back(c.propagate(sc, c.explain_weak_eval(sc)));
|
||||||
result.push_back(c.get_dependency(index));
|
result.append(e.e->deps);
|
||||||
|
if (!index.is_null())
|
||||||
|
result.push_back(c.get_dependency(index));
|
||||||
if (e.e == last.e)
|
if (e.e == last.e)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,9 +128,11 @@ namespace polysat {
|
||||||
|
|
||||||
viable::entry* find_overlap(rational const& val, entry* entries);
|
viable::entry* find_overlap(rational const& val, entry* entries);
|
||||||
|
|
||||||
bool refine_disequal_lin(pvar v, rational const& val);
|
bool check_disequal_lin(pvar v, rational const& val);
|
||||||
|
|
||||||
bool refine_equal_lin(pvar v, rational const& val);
|
bool check_equal_lin(pvar v, rational const& val);
|
||||||
|
|
||||||
|
bool check_fixed_bits(pvar v, rational const& val);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -75,6 +75,9 @@ namespace polysat {
|
||||||
void solver::collect_statistics(statistics& st) const {
|
void solver::collect_statistics(statistics& st) const {
|
||||||
m_intblast.collect_statistics(st);
|
m_intblast.collect_statistics(st);
|
||||||
m_core.collect_statistics(st);
|
m_core.collect_statistics(st);
|
||||||
|
st.update("polysat-conflicts", m_stats.m_num_conflicts);
|
||||||
|
st.update("polysat-axioms", m_stats.m_num_axioms);
|
||||||
|
st.update("polysat-propagations", m_stats.m_num_propagations);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::ostream& solver::display_justification(std::ostream& out, sat::ext_justification_idx idx) const {
|
std::ostream& solver::display_justification(std::ostream& out, sat::ext_justification_idx idx) const {
|
||||||
|
|
|
@ -119,6 +119,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::set_conflict(dependency_vector const& deps, char const* hint_info) {
|
void solver::set_conflict(dependency_vector const& deps, char const* hint_info) {
|
||||||
|
++m_stats.m_num_conflicts;
|
||||||
if (inconsistent())
|
if (inconsistent())
|
||||||
return;
|
return;
|
||||||
auto [lits, eqs] = explain_deps(deps);
|
auto [lits, eqs] = explain_deps(deps);
|
||||||
|
@ -127,8 +128,8 @@ namespace polysat {
|
||||||
hint = mk_proof_hint(hint_info, lits, eqs);
|
hint = mk_proof_hint(hint_info, lits, eqs);
|
||||||
auto ex = euf::th_explain::conflict(*this, lits, eqs, hint);
|
auto ex = euf::th_explain::conflict(*this, lits, eqs, hint);
|
||||||
TRACE("bv", tout << "conflict: " << lits << " ";
|
TRACE("bv", tout << "conflict: " << lits << " ";
|
||||||
for (auto [a, b] : eqs) tout << ctx.bpp(a) << " == " << ctx.bpp(b) << " ";
|
for (auto [a, b] : eqs) tout << ctx.bpp(a) << " == " << ctx.bpp(b) << " ";
|
||||||
tout << "\n"; s().display(tout));
|
tout << "\n"; s().display(tout));
|
||||||
validate_conflict(lits, eqs);
|
validate_conflict(lits, eqs);
|
||||||
ctx.set_conflict(ex);
|
ctx.set_conflict(ex);
|
||||||
}
|
}
|
||||||
|
@ -182,7 +183,6 @@ namespace polysat {
|
||||||
SASSERT(n1->get_root() == n2->get_root());
|
SASSERT(n1->get_root() == n2->get_root());
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
return { core, eqs };
|
return { core, eqs };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +248,7 @@ namespace polysat {
|
||||||
// Everything goes over expressions/literals. polysat::core is not responsible for replaying expressions.
|
// Everything goes over expressions/literals. polysat::core is not responsible for replaying expressions.
|
||||||
|
|
||||||
dependency solver::propagate(signed_constraint sc, dependency_vector const& deps, char const* hint_info) {
|
dependency solver::propagate(signed_constraint sc, dependency_vector const& deps, char const* hint_info) {
|
||||||
|
++m_stats.m_num_propagations;
|
||||||
TRACE("bv", sc.display(tout << "propagate ") << "\n");
|
TRACE("bv", sc.display(tout << "propagate ") << "\n");
|
||||||
sat::literal lit = ctx.mk_literal(constraint2expr(sc));
|
sat::literal lit = ctx.mk_literal(constraint2expr(sc));
|
||||||
if (s().value(lit) == l_true)
|
if (s().value(lit) == l_true)
|
||||||
|
@ -280,6 +281,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::propagate(dependency const& d, bool sign, dependency_vector const& deps, char const* hint_info) {
|
void solver::propagate(dependency const& d, bool sign, dependency_vector const& deps, char const* hint_info) {
|
||||||
|
++m_stats.m_num_propagations;
|
||||||
TRACE("bv", tout << "propagate " << d << " " << sign << "\n");
|
TRACE("bv", tout << "propagate " << d << " " << sign << "\n");
|
||||||
auto [core, eqs] = explain_deps(deps);
|
auto [core, eqs] = explain_deps(deps);
|
||||||
SASSERT(d.is_bool_var() || d.is_eq());
|
SASSERT(d.is_bool_var() || d.is_eq());
|
||||||
|
@ -322,6 +324,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool solver::add_axiom(char const* name, constraint_or_dependency const* begin, constraint_or_dependency const* end, bool is_redundant) {
|
bool solver::add_axiom(char const* name, constraint_or_dependency const* begin, constraint_or_dependency const* end, bool is_redundant) {
|
||||||
|
++m_stats.m_num_axioms;
|
||||||
if (inconsistent())
|
if (inconsistent())
|
||||||
return false;
|
return false;
|
||||||
TRACE("bv", tout << "add " << name << "\n");
|
TRACE("bv", tout << "add " << name << "\n");
|
||||||
|
@ -357,6 +360,7 @@ namespace polysat {
|
||||||
}
|
}
|
||||||
|
|
||||||
void solver::add_axiom(char const* name, std::initializer_list<sat::literal> const& clause) {
|
void solver::add_axiom(char const* name, std::initializer_list<sat::literal> const& clause) {
|
||||||
|
++m_stats.m_num_axioms;
|
||||||
bool is_redundant = false;
|
bool is_redundant = false;
|
||||||
sat::literal_vector lits;
|
sat::literal_vector lits;
|
||||||
proof_hint* hint = nullptr;
|
proof_hint* hint = nullptr;
|
||||||
|
|
|
@ -74,6 +74,9 @@ namespace polysat {
|
||||||
|
|
||||||
struct stats {
|
struct stats {
|
||||||
void reset() { memset(this, 0, sizeof(stats)); }
|
void reset() { memset(this, 0, sizeof(stats)); }
|
||||||
|
unsigned m_num_conflicts;
|
||||||
|
unsigned m_num_propagations;
|
||||||
|
unsigned m_num_axioms;
|
||||||
stats() { reset(); }
|
stats() { reset(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue