mirror of
https://github.com/Z3Prover/z3
synced 2025-08-12 22:20:54 +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 {
|
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);
|
||||||
|
|
||||||
|
|
|
@ -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();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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"));
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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;
|
||||||
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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));
|
||||||
});
|
});
|
||||||
|
|
|
@ -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();
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue