3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-22 02:57:50 +00:00

use lazy explanation function for slices, use euf-bv-plugin to extract slices

This commit is contained in:
Nikolaj Bjorner 2023-12-23 11:10:18 -08:00
parent 5bbec43235
commit fbbad72c29
11 changed files with 243 additions and 197 deletions

View file

@ -389,11 +389,11 @@ namespace polysat {
}
}
void core::get_bitvector_suffixes(pvar v, justified_slices& out) {
void core::get_bitvector_suffixes(pvar v, offset_slices& out) {
s.get_bitvector_suffixes(v, out);
}
void core::get_fixed_bits(pvar v, justified_fixed_bits& fixed_bits) {
void core::get_fixed_bits(pvar v, fixed_bits_vector& fixed_bits) {
s.get_fixed_bits(v, fixed_bits);
}

View file

@ -83,8 +83,8 @@ namespace polysat {
void propagate_unsat_core();
void propagate(constraint_id id, signed_constraint& sc, lbool value, dependency const& d);
void get_bitvector_suffixes(pvar v, justified_slices& out);
void get_fixed_bits(pvar v, justified_fixed_bits& fixed_bits);
void get_bitvector_suffixes(pvar v, offset_slices& out);
void get_fixed_bits(pvar v, fixed_bits_vector& fixed_bits);
bool inconsistent() const;
void add_watch(unsigned idx, unsigned var);

View file

@ -17,8 +17,6 @@ Author:
namespace polysat {
using fixed_bits_vector = vector<fixed_bits>;
bool get_eq_fixed_lsb(pdd const& p, fixed_bits& out);
bool get_eq_fixed_bits(pdd const& p, fixed_bits& out);

View file

@ -29,7 +29,7 @@ namespace polysat {
using pvar_vector = unsigned_vector;
using theory_var_pair = std::pair<theory_var, theory_var>;
using theory_var_pairs = svector<theory_var_pair>;
using offset_claim = std::tuple<pvar, pvar, unsigned>;
inline const pvar null_var = UINT_MAX;
class signed_constraint;
@ -37,22 +37,22 @@ namespace polysat {
class dependency {
struct axiom_t {};
std::variant<axiom_t, sat::literal, theory_var_pair, theory_var_pairs> m_data;
std::variant<axiom_t, sat::literal, theory_var_pair, offset_claim> m_data;
unsigned m_level;
dependency(): m_data(axiom_t()), m_level(0) {}
public:
dependency(sat::literal lit, unsigned level) : m_data(lit), m_level(level) {}
dependency(theory_var v1, theory_var v2, unsigned level) : m_data(std::make_pair(v1, v2)), m_level(level) {}
dependency(theory_var_pairs& j, unsigned level) : m_data(j), m_level(level) {}
dependency(offset_claim const& c, unsigned level) : m_data(c), m_level(level) {}
static dependency axiom() { return dependency(); }
bool is_null() const { return is_literal() && *std::get_if<sat::literal>(&m_data) == sat::null_literal; }
bool is_axiom() const { return std::holds_alternative<axiom_t>(m_data); }
bool is_eqs() const { return std::holds_alternative<theory_var_pairs>(m_data); }
bool is_eq() const { return std::holds_alternative<theory_var_pair>(m_data); }
bool is_literal() const { return std::holds_alternative<sat::literal>(m_data); }
bool is_offset_claim() const { return std::holds_alternative<offset_claim>(m_data); }
sat::literal literal() const { SASSERT(is_literal()); return *std::get_if<sat::literal>(&m_data); }
theory_var_pair eq() const { SASSERT(!is_literal()); return *std::get_if<theory_var_pair>(&m_data); }
theory_var_pairs const& eqs() const { SASSERT(!is_literal()); return *std::get_if<theory_var_pairs>(&m_data); }
offset_claim offset() const { return *std::get_if<offset_claim>(&m_data); }
unsigned level() const { return m_level; }
void set_level(unsigned level) { m_level = level; }
dependency operator~() const { SASSERT(is_literal()); return dependency(~literal(), level()); }
@ -70,10 +70,8 @@ namespace polysat {
else if (d.is_eq())
return out << "v" << d.eq().first << " == v" << d.eq().second << "@" << d.level();
else {
char const* sep = "";
for (auto [v1, v2] : d.eqs())
out << sep << "v" << d.eq().first << " == v" << d.eq().second, sep = ", ";
return out << " @" << d.level();
auto [v1, v2, offset] = d.offset();
return out << "v" << v1 << " == v" << v2 << " offset " << offset << "@" << d.level();
}
}
@ -90,17 +88,16 @@ namespace polysat {
fixed_bits(unsigned hi, unsigned lo, rational value) : hi(hi), lo(lo), value(value) {}
};
struct justified_slice {
struct offset_slice {
pvar v;
unsigned offset;
dependency dep;
};
inline std::ostream& operator<<(std::ostream& out, justified_slice const& js) {
return out << "v" << js.v << "[" << js.offset << "[ @" << js.dep;
inline std::ostream& operator<<(std::ostream& out, offset_slice const& js) {
return out << "v" << js.v << "[" << js.offset << "[ @";
}
using justified_fixed_bits = vector<std::pair<fixed_bits, dependency>>;
using fixed_bits_vector = svector<fixed_bits>;
using dependency_vector = vector<dependency>;
using constraint_or_dependency = std::variant<signed_constraint, dependency>;
@ -110,7 +107,7 @@ namespace polysat {
using core_vector = std::initializer_list<constraint_or_dependency>;
using constraint_id_vector = svector<constraint_id>;
using constraint_id_list = std::initializer_list<constraint_id>;
using justified_slices = vector<justified_slice>;
using offset_slices = vector<offset_slice>;
using eq_justification = svector<std::pair<theory_var, theory_var>>;
//
@ -127,10 +124,10 @@ namespace polysat {
virtual void propagate(dependency const& d, bool sign, constraint_id_vector const& deps) = 0;
virtual trail_stack& trail() = 0;
virtual bool inconsistent() const = 0;
virtual void get_bitvector_suffixes(pvar v, justified_slices& out) = 0;
virtual void get_bitvector_sub_slices(pvar v, justified_slices& out) = 0;
virtual void get_bitvector_super_slices(pvar v, justified_slices& out) = 0;
virtual void get_fixed_bits(pvar v, justified_fixed_bits& fixed_bits) = 0;
virtual void get_bitvector_suffixes(pvar v, offset_slices& out) = 0;
virtual void get_bitvector_sub_slices(pvar v, offset_slices& out) = 0;
virtual void get_bitvector_super_slices(pvar v, offset_slices& out) = 0;
virtual void get_fixed_bits(pvar v, fixed_bits_vector& fixed_bits) = 0;
};
}

View file

@ -103,7 +103,7 @@ namespace polysat {
return l_false; // conflict already added
#endif
justified_slices overlaps;
offset_slices overlaps;
c.get_bitvector_suffixes(v, overlaps);
std::sort(overlaps.begin(), overlaps.end(), [&](auto const& x, auto const& y) { return c.size(x.v) > c.size(y.v); });
@ -111,7 +111,7 @@ namespace polysat {
// max size should always be present, regardless of whether we have intervals there (to make sure all fixed bits are considered)
widths_set.insert(c.size(v));
for (auto const& [v, offset, j] : overlaps)
for (auto const& [v, offset] : overlaps)
for (layer const& l : m_units[v].get_layers())
widths_set.insert(l.bit_width);
@ -147,7 +147,7 @@ namespace polysat {
lbool viable::find_on_layers(
pvar const v,
unsigned_vector const& widths,
justified_slices const& overlaps,
offset_slices const& overlaps,
fixed_bits_info const& fbi,
rational const& to_cover_lo,
rational const& to_cover_hi,
@ -201,7 +201,7 @@ namespace polysat {
pvar const v,
unsigned const w_idx,
unsigned_vector const& widths,
justified_slices const& overlaps,
offset_slices const& overlaps,
fixed_bits_info const& fbi,
rational const& to_cover_lo,
rational const& to_cover_hi,
@ -240,7 +240,7 @@ namespace polysat {
// find relevant interval lists
svector<entry_cursor> ecs;
for (auto const& [x, offset, j] : overlaps) {
for (auto const& [x, offset] : overlaps) {
if (c.size(x) < w) // note that overlaps are sorted by variable size descending
break;
if (entry* e = m_units[x].get_entries(w)) {
@ -614,17 +614,17 @@ namespace polysat {
out_fbi.reset(v_sz);
auto& [fixed, just_src, just_side_cond, just_slice] = out_fbi;
justified_fixed_bits fbs;
fixed_bits_vector fbs;
c.get_fixed_bits(v, fbs);
for (auto const& [fb, d] : fbs) {
for (auto const& fb : fbs) {
LOG("slicing fixed bits: v" << v << "[" << fb.hi << ":" << fb.lo << "] = " << fb.value);
for (unsigned i = fb.lo; i <= fb.hi; ++i) {
SASSERT(out_fbi.just_src[i].empty()); // since we don't get overlapping ranges from collect_fixed.
SASSERT(out_fbi.just_side_cond[i].empty());
SASSERT(out_fbi.just_slicing[i].empty());
out_fbi.fixed[i] = to_lbool(fb.value.get_bit(i - fb.lo));
out_fbi.just_slicing[i].push_back({ fb, d });
out_fbi.just_slicing[i].push_back(fb);
}
}

View file

@ -107,7 +107,7 @@ namespace polysat {
svector<lbool> fixed;
vector<vector<signed_constraint>> just_src;
vector<vector<signed_constraint>> just_side_cond;
vector<justified_fixed_bits> just_slicing;
vector<fixed_bits_vector> just_slicing;
bool is_empty() const {
SASSERT_EQ(fixed.empty(), just_src.empty());
@ -186,7 +186,7 @@ namespace polysat {
lbool find_on_layers(
pvar v,
unsigned_vector const& widths,
justified_slices const& overlaps,
offset_slices const& overlaps,
fixed_bits_info const& fbi,
rational const& to_cover_lo,
rational const& to_cover_hi,
@ -196,7 +196,7 @@ namespace polysat {
pvar v,
unsigned w_idx,
unsigned_vector const& widths,
justified_slices const& overlaps,
offset_slices const& overlaps,
fixed_bits_info const& fbi,
rational const& to_cover_lo,
rational const& to_cover_hi,