diff --git a/src/math/polysat/fixed_bits.h b/src/math/polysat/fixed_bits.h index f37eafeb1..968388b35 100644 --- a/src/math/polysat/fixed_bits.h +++ b/src/math/polysat/fixed_bits.h @@ -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; - bool get_eq_fixed_lsb(pdd const& p, fixed_bits& out); bool get_eq_fixed_bits(pdd const& p, fixed_bits& out); diff --git a/src/math/polysat/slicing.cpp b/src/math/polysat/slicing.cpp index 04fe8c4fc..799b8bbff 100644 --- a/src/math/polysat/slicing.cpp +++ b/src/math/polysat/slicing.cpp @@ -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 const& on_lit) { + void slicing::explain_prefix(pvar v, pvar x, std::function 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(); } } diff --git a/src/math/polysat/slicing.h b/src/math/polysat/slicing.h index f9f90610b..e945a05e2 100644 --- a/src/math/polysat/slicing.h +++ b/src/math/polysat/slicing.h @@ -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 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 const& on_lit, std::function 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 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; + void collect_prefixes(pvar v, pvar_vector& out) override; + void explain_prefix(pvar v, pvar x, std::function 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 const& on_lit, std::function const& on_var); + void collect_fixed(pvar v, justified_fixed_bits_vector& out) override; + void explain_fixed(enode* just, std::function const& on_lit, std::function const& on_var) override; /** * Collect variables that are equivalent to v (including v itself) diff --git a/src/math/polysat/solver.cpp b/src/math/polysat/solver.cpp index ed05dd498..4720ee597 100644 --- a/src/math/polysat/solver.cpp +++ b/src/math/polysat/solver.cpp @@ -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")); diff --git a/src/math/polysat/solver.h b/src/math/polysat/solver.h index 046ce20d3..0b56dde7d 100644 --- a/src/math/polysat/solver.h +++ b/src/math/polysat/solver.h @@ -163,7 +163,8 @@ namespace polysat { params_ref m_params; config_t m_config; - mutable scoped_ptr_vector m_pdd; + mutable scoped_ptr_vector 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 m_kind; diff --git a/src/math/polysat/types.h b/src/math/polysat/types.h index 48892d483..8999881e4 100644 --- a/src/math/polysat/types.h +++ b/src/math/polysat/types.h @@ -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; + + 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 const& on_lit, std::function 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 const& on_lit) = 0; + }; + } diff --git a/src/math/polysat/viable.cpp b/src/math/polysat/viable.cpp index 6ccbc557a..cd1bf3244 100644 --- a/src/math/polysat/viable.cpp +++ b/src/math/polysat/viable.cpp @@ -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& just_src = out_fbi.just_src; 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)); }); diff --git a/src/math/polysat/viable.h b/src/math/polysat/viable.h index 243f44cd6..dc8f02de2 100644 --- a/src/math/polysat/viable.h +++ b/src/math/polysat/viable.h @@ -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, 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 find_value(rational const& val, entry* entries); public: - viable(solver& s); + viable(solver& s, viable_slicing_interface& slicing); ~viable();