3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-13 06:30:54 +00:00

viable_slicing_interface

This commit is contained in:
Jakob Rath 2023-12-21 15:31:18 +01:00
parent bb49c71ba9
commit c6ee5b76ad
8 changed files with 69 additions and 48 deletions

View file

@ -17,20 +17,6 @@ Author:
namespace polysat { namespace polysat {
struct fixed_bits {
unsigned hi = 0;
unsigned lo = 0;
rational value;
/// The constraint is equivalent to setting fixed bits on a variable.
// bool is_equivalent;
fixed_bits() = default;
fixed_bits(unsigned hi, unsigned lo, rational value): hi(hi), lo(lo), value(value) {}
};
using fixed_bits_vector = vector<fixed_bits>;
bool get_eq_fixed_lsb(pdd const& p, fixed_bits& out); bool get_eq_fixed_lsb(pdd const& p, fixed_bits& out);
bool get_eq_fixed_bits(pdd const& p, fixed_bits& out); bool get_eq_fixed_bits(pdd const& p, fixed_bits& out);

View file

@ -649,7 +649,7 @@ namespace polysat {
on_lit(d.lit()); on_lit(d.lit());
} }
else { else {
// equivalence between to variables cannot be due to value assignment // equivalence between two variables cannot be due to value assignment
UNREACHABLE(); UNREACHABLE();
} }
} }
@ -1411,7 +1411,7 @@ namespace polysat {
(void)add_value(v, value, sat::null_literal); (void)add_value(v, value, sat::null_literal);
} }
void slicing::collect_simple_overlaps(pvar v, pvar_vector& out) { void slicing::collect_prefixes(pvar v, pvar_vector& out) {
unsigned const first_out = out.size(); unsigned const first_out = out.size();
enode* const sv = var2slice(v); enode* const sv = var2slice(v);
unsigned const v_width = width(sv); unsigned const v_width = width(sv);
@ -1520,7 +1520,7 @@ namespace polysat {
SASSERT(all_of(m_egraph.nodes(), [](enode* n) { return !n->is_marked1(); })); SASSERT(all_of(m_egraph.nodes(), [](enode* n) { return !n->is_marked1(); }));
} }
void slicing::explain_simple_overlap(pvar v, pvar x, std::function<void(sat::literal)> const& on_lit) { void slicing::explain_prefix(pvar v, pvar x, std::function<void(sat::literal)> const& on_lit) {
SASSERT(width(var2slice(x)) <= width(var2slice(v))); SASSERT(width(var2slice(x)) <= width(var2slice(v)));
SASSERT(m_marked_lits.empty()); SASSERT(m_marked_lits.empty());
SASSERT(m_tmp_deps.empty()); SASSERT(m_tmp_deps.empty());
@ -1557,7 +1557,7 @@ namespace polysat {
on_lit(d.lit()); on_lit(d.lit());
} }
else { else {
// equivalence between to variables cannot be due to value assignment // equivalence between two variables cannot be due to value assignment
UNREACHABLE(); UNREACHABLE();
} }
} }

View file

@ -35,7 +35,7 @@ namespace polysat {
class solver; class solver;
class slicing final { class slicing final : public viable_slicing_interface {
friend class test_slicing; friend class test_slicing;
@ -341,7 +341,7 @@ namespace polysat {
pvar mk_concat(std::initializer_list<pvar> args); pvar mk_concat(std::initializer_list<pvar> args);
// Find hi, lo such that x = src[hi:lo]. // Find hi, lo such that x = src[hi:lo].
bool is_extract(pvar x, pvar src, unsigned& out_hi, unsigned& out_lo); bool is_extract(pvar x, pvar src, unsigned& out_hi, unsigned& out_lo) override;
// Track value assignments to variables (and propagate to subslices) // Track value assignments to variables (and propagate to subslices)
void add_value(pvar v, rational const& value); void add_value(pvar v, rational const& value);
@ -363,20 +363,12 @@ namespace polysat {
void explain_value(pvar v, std::function<void(sat::literal)> const& on_lit, std::function<void(pvar)> const& on_var); void explain_value(pvar v, std::function<void(sat::literal)> const& on_lit, std::function<void(pvar)> const& on_var);
/** For a given variable v, find the set of variables w such that w = v[|w|:0]. */ /** For a given variable v, find the set of variables w such that w = v[|w|:0]. */
void collect_simple_overlaps(pvar v, pvar_vector& out); void collect_prefixes(pvar v, pvar_vector& out) override;
void explain_simple_overlap(pvar v, pvar x, std::function<void(sat::literal)> const& on_lit); void explain_prefix(pvar v, pvar x, std::function<void(sat::literal)> const& on_lit) override;
struct justified_fixed_bits : public fixed_bits {
enode* just;
justified_fixed_bits(unsigned hi, unsigned lo, rational value, enode* just): fixed_bits(hi, lo, value), just(just) {}
};
using justified_fixed_bits_vector = vector<justified_fixed_bits>;
/** Collect fixed portions of the variable v */ /** Collect fixed portions of the variable v */
void collect_fixed(pvar v, justified_fixed_bits_vector& out); void collect_fixed(pvar v, justified_fixed_bits_vector& out) override;
void explain_fixed(enode* just, std::function<void(sat::literal)> const& on_lit, std::function<void(pvar)> const& on_var); void explain_fixed(enode* just, std::function<void(sat::literal)> const& on_lit, std::function<void(pvar)> const& on_var) override;
/** /**
* Collect variables that are equivalent to v (including v itself) * Collect variables that are equivalent to v (including v itself)

View file

@ -48,7 +48,8 @@ namespace polysat {
solver::solver(reslimit& lim, smt_params const& p): solver::solver(reslimit& lim, smt_params const& p):
m_lim(lim), m_lim(lim),
m_viable(*this), m_slicing(*this),
m_viable(*this, m_slicing),
m_viable_fallback(*this), m_viable_fallback(*this),
m_conflict(*this), m_conflict(*this),
m_simplify_clause(*this), m_simplify_clause(*this),
@ -58,7 +59,6 @@ namespace polysat {
m_free_pvars(m_size, m_activity), m_free_pvars(m_size, m_activity),
m_constraints(*this), m_constraints(*this),
m_names(*this), m_names(*this),
m_slicing(*this),
m_search(*this) { m_search(*this) {
updt_smt_params(p); updt_smt_params(p);
updt_polysat_params(gparams::get_module("polysat")); updt_polysat_params(gparams::get_module("polysat"));

View file

@ -163,7 +163,8 @@ namespace polysat {
params_ref m_params; params_ref m_params;
config_t m_config; config_t m_config;
mutable scoped_ptr_vector<dd::pdd_manager> m_pdd; mutable scoped_ptr_vector<pdd_manager> m_pdd;
slicing m_slicing;
viable m_viable; // viable sets per variable viable m_viable; // viable sets per variable
viable_fallback m_viable_fallback; // fallback for viable, using bitblasting over univariate constraints viable_fallback m_viable_fallback; // fallback for viable, using bitblasting over univariate constraints
conflict m_conflict; conflict m_conflict;
@ -178,7 +179,6 @@ namespace polysat {
// Per constraint state // Per constraint state
constraint_manager m_constraints; constraint_manager m_constraints;
name_manager m_names; name_manager m_names;
slicing m_slicing;
// Per variable information // Per variable information
svector<pvar_kind> m_kind; svector<pvar_kind> m_kind;

View file

@ -11,6 +11,7 @@ Author:
--*/ --*/
#pragma once #pragma once
#include "ast/euf/euf_egraph.h"
#include "util/trail.h" #include "util/trail.h"
#include "util/lbool.h" #include "util/lbool.h"
#include "util/map.h" #include "util/map.h"
@ -74,4 +75,44 @@ namespace polysat {
return out << ")"; return out << ")";
} }
/// x[hi:lo] = value
struct fixed_bits {
unsigned hi = 0;
unsigned lo = 0;
rational value;
fixed_bits() = default;
fixed_bits(unsigned hi, unsigned lo, rational value): hi(hi), lo(lo), value(value) {}
};
struct justified_fixed_bits : public fixed_bits {
euf::enode* just;
justified_fixed_bits(unsigned hi, unsigned lo, rational value, euf::enode* just): fixed_bits(hi, lo, value), just(just) {}
};
using justified_fixed_bits_vector = vector<justified_fixed_bits>;
class viable_slicing_interface {
public:
using enode = euf::enode;
using enode_vector = euf::enode_vector;
using enode_pair = euf::enode_pair;
using enode_pair_vector = euf::enode_pair_vector;
virtual ~viable_slicing_interface() {}
// Find hi, lo such that x = src[hi:lo].
virtual bool is_extract(pvar x, pvar src, unsigned& out_hi, unsigned& out_lo) = 0;
/** Collect fixed portions of the variable v */
virtual void collect_fixed(pvar v, justified_fixed_bits_vector& out) = 0;
virtual void explain_fixed(enode* just, std::function<void(sat::literal)> const& on_lit, std::function<void(pvar)> const& on_var) = 0;
/** For a given variable v, find the set of variables w such that w = v[|w|:0]. */
virtual void collect_prefixes(pvar v, pvar_vector& out) = 0;
virtual void explain_prefix(pvar v, pvar x, std::function<void(sat::literal)> const& on_lit) = 0;
};
} }

View file

@ -47,8 +47,9 @@ namespace polysat {
} }
}; };
viable::viable(solver& s): viable::viable(solver& s, viable_slicing_interface& slicing):
s(s), s(s),
m_slicing(slicing),
m_forbidden_intervals(s) { m_forbidden_intervals(s) {
} }
@ -234,7 +235,7 @@ namespace polysat {
} }
for (pvar x : vars_to_explain) { for (pvar x : vars_to_explain) {
s.m_slicing.explain_simple_overlap(v, x, [this, &add_reason](sat::literal l) { m_slicing.explain_prefix(v, x, [this, &add_reason](sat::literal l) {
add_reason(s.lit2cnstr(l)); add_reason(s.lit2cnstr(l));
}); });
} }
@ -805,7 +806,7 @@ namespace polysat {
side_cond.push_back(s.lit2cnstr(lit)); side_cond.push_back(s.lit2cnstr(lit));
} }
for (slicing::enode* n : fbi.just_slicing[i]) { for (slicing::enode* n : fbi.just_slicing[i]) {
s.m_slicing.explain_fixed(n, [&](sat::literal lit) { m_slicing.explain_fixed(n, [&](sat::literal lit) {
if (!added_src.contains(lit)) { if (!added_src.contains(lit)) {
added_src.insert(lit); added_src.insert(lit);
src.push_back(s.lit2cnstr(lit)); src.push_back(s.lit2cnstr(lit));
@ -909,8 +910,8 @@ namespace polysat {
vector<sat::literal_vector>& just_src = out_fbi.just_src; vector<sat::literal_vector>& just_src = out_fbi.just_src;
vector<sat::literal_vector>& just_side_cond = out_fbi.just_side_cond; vector<sat::literal_vector>& just_side_cond = out_fbi.just_side_cond;
slicing::justified_fixed_bits_vector fbs; justified_fixed_bits_vector fbs;
s.m_slicing.collect_fixed(v, fbs); m_slicing.collect_fixed(v, fbs);
for (auto const& fb : fbs) { for (auto const& fb : fbs) {
LOG("slicing fixed bits: v" << v << "[" << fb.hi << ":" << fb.lo << "] = " << fb.value); LOG("slicing fixed bits: v" << v << "[" << fb.hi << ":" << fb.lo << "] = " << fb.value);
@ -953,7 +954,7 @@ namespace polysat {
}; };
auto add_slicing = [this, &add_literal](slicing::enode* n) { auto add_slicing = [this, &add_literal](slicing::enode* n) {
s.m_slicing.explain_fixed(n, [&](sat::literal lit) { m_slicing.explain_fixed(n, [&](sat::literal lit) {
add_literal(lit); add_literal(lit);
}, [&](pvar v){ }, [&](pvar v){
LOG("from slicing: v" << v); LOG("from slicing: v" << v);
@ -1503,7 +1504,7 @@ namespace polysat {
return l_false; // conflict already added return l_false; // conflict already added
pvar_vector overlaps; pvar_vector overlaps;
s.m_slicing.collect_simple_overlaps(v, overlaps); m_slicing.collect_prefixes(v, overlaps);
std::sort(overlaps.begin(), overlaps.end(), [&](pvar x, pvar y) { return s.size(x) > s.size(y); }); std::sort(overlaps.begin(), overlaps.end(), [&](pvar x, pvar y) { return s.size(x) > s.size(y); });
uint_set widths_set; uint_set widths_set;
@ -1513,7 +1514,7 @@ namespace polysat {
LOG("Overlaps with v" << v << ":"); LOG("Overlaps with v" << v << ":");
for (pvar x : overlaps) { for (pvar x : overlaps) {
unsigned hi, lo; unsigned hi, lo;
if (s.m_slicing.is_extract(x, v, hi, lo)) if (m_slicing.is_extract(x, v, hi, lo))
LOG(" v" << x << " = v" << v << "[" << hi << ":" << lo << "]"); LOG(" v" << x << " = v" << v << "[" << hi << ":" << lo << "]");
else else
LOG(" v" << x << " not extracted from v" << v << "; size " << s.size(x)); LOG(" v" << x << " not extracted from v" << v << "; size " << s.size(x));
@ -1939,7 +1940,7 @@ namespace polysat {
core.insert_vars(c); core.insert_vars(c);
} }
for (pvar x : vars_to_explain) { for (pvar x : vars_to_explain) {
s.m_slicing.explain_simple_overlap(v, x, [this, &core](sat::literal l) { m_slicing.explain_prefix(v, x, [this, &core](sat::literal l) {
core.insert(s.lit2cnstr(l)); core.insert(s.lit2cnstr(l));
}); });
} }
@ -1994,7 +1995,7 @@ namespace polysat {
} }
for (pvar x : vars_to_explain) { for (pvar x : vars_to_explain) {
s.m_slicing.explain_simple_overlap(v, x, [this, &core, &lemma](sat::literal l) { m_slicing.explain_prefix(v, x, [this, &core, &lemma](sat::literal l) {
lemma.insert(~l); lemma.insert(~l);
core.insert(s.lit2cnstr(l)); core.insert(s.lit2cnstr(l));
}); });

View file

@ -47,7 +47,8 @@ namespace polysat {
friend class conflict; friend class conflict;
solver& s; solver& s;
forbidden_intervals m_forbidden_intervals; viable_slicing_interface& m_slicing;
forbidden_intervals m_forbidden_intervals;
struct entry final : public dll_base<entry>, public fi_record { struct entry final : public dll_base<entry>, public fi_record {
/// whether the entry has been created by refinement (from constraints in 'fi_record::src') /// whether the entry has been created by refinement (from constraints in 'fi_record::src')
@ -251,7 +252,7 @@ namespace polysat {
std::pair<entry*, bool> find_value(rational const& val, entry* entries); std::pair<entry*, bool> find_value(rational const& val, entry* entries);
public: public:
viable(solver& s); viable(solver& s, viable_slicing_interface& slicing);
~viable(); ~viable();