3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-07-31 16:33:18 +00:00

Merge branch 'master' into polysat

This commit is contained in:
Jakob Rath 2022-07-21 12:56:50 +02:00
commit e168d8a2eb
109 changed files with 4372 additions and 2743 deletions

View file

@ -1741,6 +1741,87 @@ namespace dd {
return (*this) * rational::power_of_two(n);
}
/**
* \brief substitute variable v by r.
* This base line implementation is simplistic and does not use operator caching.
*/
pdd pdd::subst_pdd(unsigned v, pdd const& r) const {
if (is_val())
return *this;
if (m.m_var2level[var()] < m.m_var2level[v])
return *this;
pdd l = lo().subst_pdd(v, r);
pdd h = hi().subst_pdd(v, r);
if (var() == v)
return r*h + l;
else if (l == lo() && h == hi())
return *this;
else
return m.mk_var(var())*h + l;
}
std::pair<unsigned_vector, pdd> pdd::var_factors() const {
if (is_val())
return { unsigned_vector(), *this };
unsigned v = var();
if (lo().is_val()) {
if (!lo().is_zero())
return { unsigned_vector(), *this };
auto [vars, p] = hi().var_factors();
vars.push_back(v);
return {vars, p};
}
auto [lo_vars, q] = lo().var_factors();
if (lo_vars.empty())
return { unsigned_vector(), *this };
unsigned_vector lo_and_hi;
auto merge = [&](unsigned_vector& lo_vars, unsigned_vector& hi_vars) {
unsigned ir = 0, jr = 0;
for (unsigned i = 0, j = 0; i < lo_vars.size() || j < hi_vars.size(); ) {
if (i == lo_vars.size())
hi_vars[jr++] = hi_vars[j++];
else if (j == hi_vars.size())
lo_vars[ir++] = lo_vars[i++];
else if (lo_vars[i] == hi_vars[j]) {
lo_and_hi.push_back(lo_vars[i]);
++i;
++j;
}
else if (m.m_var2level[lo_vars[i]] > m.m_var2level[hi_vars[j]])
hi_vars[jr++] = hi_vars[j++];
else
lo_vars[ir++] = lo_vars[i++];
}
lo_vars.shrink(ir);
hi_vars.shrink(jr);
};
auto mul = [&](unsigned_vector const& vars, pdd p) {
for (auto v : vars)
p *= m.mk_var(v);
return p;
};
auto [hi_vars, p] = hi().var_factors();
if (lo_vars.back() == v) {
lo_vars.pop_back();
merge(lo_vars, hi_vars);
lo_and_hi.push_back(v);
return { lo_and_hi, mul(lo_vars, q) + mul(hi_vars, p) };
}
if (hi_vars.empty())
return { unsigned_vector(), *this };
merge(lo_vars, hi_vars);
hi_vars.push_back(v);
if (lo_and_hi.empty())
return { unsigned_vector(), *this };
else
return { lo_and_hi, mul(lo_vars, q) + mul(hi_vars, p) };
}
std::ostream& operator<<(std::ostream& out, pdd const& b) { return b.display(out); }
void pdd_iterator::next() {

View file

@ -447,11 +447,22 @@ namespace dd {
bool resolve(unsigned v, pdd const& other, pdd& result) { return m.resolve(v, *this, other, result); }
pdd reduce(unsigned v, pdd const& other) const { return m.reduce(v, *this, other); }
/**
* \brief factor out variables
*/
std::pair<unsigned_vector, pdd> var_factors() const;
pdd subst_val0(vector<std::pair<unsigned, rational>> const& s) const { return m.subst_val0(*this, s); }
pdd subst_val(pdd const& s) const { return m.subst_val(*this, s); }
pdd subst_val(vector<std::pair<unsigned, rational>> const& s) const { return m.subst_val0(*this, s); }
pdd subst_val(unsigned v, rational const& val) const { return m.subst_val(*this, v, val); }
pdd subst_add(unsigned var, rational const& val) { return m.subst_add(*this, var, val); }
/**
* \brief substitute variable v by r.
*/
pdd subst_pdd(unsigned v, pdd const& r) const;
std::ostream& display(std::ostream& out) const { return m.display(out, *this); }
bool operator==(pdd const& other) const { return root == other.root; }
bool operator!=(pdd const& other) const { return root != other.root; }

View file

@ -27,7 +27,33 @@ typedef dep_intervals::with_deps_t w_dep;
class pdd_interval {
dep_intervals& m_dep_intervals;
std::function<void (unsigned, bool, scoped_dep_interval&)> m_var2interval;
// retrieve intervals after distributing multiplication over addition.
template <w_dep wd>
void get_interval_distributed(pdd const& p, scoped_dep_interval& i, scoped_dep_interval& ret) {
bool deps = wd == w_dep::with_deps;
if (p.is_val()) {
if (deps)
m_dep_intervals.mul<dep_intervals::with_deps>(p.val(), i, ret);
else
m_dep_intervals.mul<dep_intervals::without_deps>(p.val(), i, ret);
return;
}
scoped_dep_interval hi(m()), lo(m()), t(m()), a(m());
get_interval_distributed<wd>(p.lo(), i, lo);
m_var2interval(p.var(), deps, a);
if (deps) {
m_dep_intervals.mul<dep_intervals::with_deps>(a, i, t);
get_interval_distributed<wd>(p.hi(), t, hi);
m_dep_intervals.add<dep_intervals::with_deps>(hi, lo, ret);
}
else {
m_dep_intervals.mul<dep_intervals::without_deps>(a, i, t);
get_interval_distributed<wd>(p.hi(), t, hi);
m_dep_intervals.add<dep_intervals::without_deps>(hi, lo, ret);
}
}
public:
pdd_interval(dep_intervals& d): m_dep_intervals(d) {}
@ -57,5 +83,11 @@ public:
}
}
template <w_dep wd>
void get_interval_distributed(pdd const& p, scoped_dep_interval& ret) {
scoped_dep_interval i(m());
m_dep_intervals.set_interval_for_scalar(i, rational::one());
get_interval_distributed<wd>(p, i, ret);
}
};
}