mirror of
https://github.com/Z3Prover/z3
synced 2025-08-10 13:10:50 +00:00
viable_slicing_interface
This commit is contained in:
parent
bb49c71ba9
commit
c6ee5b76ad
8 changed files with 69 additions and 48 deletions
|
@ -17,20 +17,6 @@ Author:
|
|||
|
||||
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_bits(pdd const& p, fixed_bits& out);
|
||||
|
||||
|
|
|
@ -649,7 +649,7 @@ namespace polysat {
|
|||
on_lit(d.lit());
|
||||
}
|
||||
else {
|
||||
// equivalence between to variables cannot be due to value assignment
|
||||
// equivalence between two variables cannot be due to value assignment
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
@ -1411,7 +1411,7 @@ namespace polysat {
|
|||
(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();
|
||||
enode* const sv = var2slice(v);
|
||||
unsigned const v_width = width(sv);
|
||||
|
@ -1520,7 +1520,7 @@ namespace polysat {
|
|||
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(m_marked_lits.empty());
|
||||
SASSERT(m_tmp_deps.empty());
|
||||
|
@ -1557,7 +1557,7 @@ namespace polysat {
|
|||
on_lit(d.lit());
|
||||
}
|
||||
else {
|
||||
// equivalence between to variables cannot be due to value assignment
|
||||
// equivalence between two variables cannot be due to value assignment
|
||||
UNREACHABLE();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -35,7 +35,7 @@ namespace polysat {
|
|||
|
||||
class solver;
|
||||
|
||||
class slicing final {
|
||||
class slicing final : public viable_slicing_interface {
|
||||
|
||||
friend class test_slicing;
|
||||
|
||||
|
@ -341,7 +341,7 @@ namespace polysat {
|
|||
pvar mk_concat(std::initializer_list<pvar> args);
|
||||
|
||||
// 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)
|
||||
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);
|
||||
|
||||
/** 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 explain_simple_overlap(pvar v, pvar x, std::function<void(sat::literal)> const& on_lit);
|
||||
|
||||
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>;
|
||||
void collect_prefixes(pvar v, pvar_vector& out) override;
|
||||
void explain_prefix(pvar v, pvar x, std::function<void(sat::literal)> const& on_lit) override;
|
||||
|
||||
/** Collect fixed portions of the variable v */
|
||||
void collect_fixed(pvar v, justified_fixed_bits_vector& out);
|
||||
void explain_fixed(enode* just, std::function<void(sat::literal)> const& on_lit, std::function<void(pvar)> const& on_var);
|
||||
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) override;
|
||||
|
||||
/**
|
||||
* Collect variables that are equivalent to v (including v itself)
|
||||
|
|
|
@ -48,7 +48,8 @@ namespace polysat {
|
|||
|
||||
solver::solver(reslimit& lim, smt_params const& p):
|
||||
m_lim(lim),
|
||||
m_viable(*this),
|
||||
m_slicing(*this),
|
||||
m_viable(*this, m_slicing),
|
||||
m_viable_fallback(*this),
|
||||
m_conflict(*this),
|
||||
m_simplify_clause(*this),
|
||||
|
@ -58,7 +59,6 @@ namespace polysat {
|
|||
m_free_pvars(m_size, m_activity),
|
||||
m_constraints(*this),
|
||||
m_names(*this),
|
||||
m_slicing(*this),
|
||||
m_search(*this) {
|
||||
updt_smt_params(p);
|
||||
updt_polysat_params(gparams::get_module("polysat"));
|
||||
|
|
|
@ -163,7 +163,8 @@ namespace polysat {
|
|||
params_ref m_params;
|
||||
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_fallback m_viable_fallback; // fallback for viable, using bitblasting over univariate constraints
|
||||
conflict m_conflict;
|
||||
|
@ -178,7 +179,6 @@ namespace polysat {
|
|||
// Per constraint state
|
||||
constraint_manager m_constraints;
|
||||
name_manager m_names;
|
||||
slicing m_slicing;
|
||||
|
||||
// Per variable information
|
||||
svector<pvar_kind> m_kind;
|
||||
|
|
|
@ -11,6 +11,7 @@ Author:
|
|||
|
||||
--*/
|
||||
#pragma once
|
||||
#include "ast/euf/euf_egraph.h"
|
||||
#include "util/trail.h"
|
||||
#include "util/lbool.h"
|
||||
#include "util/map.h"
|
||||
|
@ -74,4 +75,44 @@ namespace polysat {
|
|||
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;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -47,8 +47,9 @@ namespace polysat {
|
|||
}
|
||||
};
|
||||
|
||||
viable::viable(solver& s):
|
||||
viable::viable(solver& s, viable_slicing_interface& slicing):
|
||||
s(s),
|
||||
m_slicing(slicing),
|
||||
m_forbidden_intervals(s) {
|
||||
}
|
||||
|
||||
|
@ -234,7 +235,7 @@ namespace polysat {
|
|||
}
|
||||
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
@ -805,7 +806,7 @@ namespace polysat {
|
|||
side_cond.push_back(s.lit2cnstr(lit));
|
||||
}
|
||||
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)) {
|
||||
added_src.insert(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_side_cond = out_fbi.just_side_cond;
|
||||
|
||||
slicing::justified_fixed_bits_vector fbs;
|
||||
s.m_slicing.collect_fixed(v, fbs);
|
||||
justified_fixed_bits_vector fbs;
|
||||
m_slicing.collect_fixed(v, fbs);
|
||||
|
||||
for (auto const& fb : fbs) {
|
||||
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) {
|
||||
s.m_slicing.explain_fixed(n, [&](sat::literal lit) {
|
||||
m_slicing.explain_fixed(n, [&](sat::literal lit) {
|
||||
add_literal(lit);
|
||||
}, [&](pvar v){
|
||||
LOG("from slicing: v" << v);
|
||||
|
@ -1503,7 +1504,7 @@ namespace polysat {
|
|||
return l_false; // conflict already added
|
||||
|
||||
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); });
|
||||
|
||||
uint_set widths_set;
|
||||
|
@ -1513,7 +1514,7 @@ namespace polysat {
|
|||
LOG("Overlaps with v" << v << ":");
|
||||
for (pvar x : overlaps) {
|
||||
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 << "]");
|
||||
else
|
||||
LOG(" v" << x << " not extracted from v" << v << "; size " << s.size(x));
|
||||
|
@ -1939,7 +1940,7 @@ namespace polysat {
|
|||
core.insert_vars(c);
|
||||
}
|
||||
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));
|
||||
});
|
||||
}
|
||||
|
@ -1994,7 +1995,7 @@ namespace polysat {
|
|||
}
|
||||
|
||||
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);
|
||||
core.insert(s.lit2cnstr(l));
|
||||
});
|
||||
|
|
|
@ -47,7 +47,8 @@ namespace polysat {
|
|||
friend class conflict;
|
||||
|
||||
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 {
|
||||
/// 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);
|
||||
|
||||
public:
|
||||
viable(solver& s);
|
||||
viable(solver& s, viable_slicing_interface& slicing);
|
||||
|
||||
~viable();
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue