3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-08-10 13:10:50 +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 {
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);

View file

@ -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();
}
}

View file

@ -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)

View file

@ -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"));

View file

@ -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;

View file

@ -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;
};
}

View file

@ -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));
});

View file

@ -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();