diff --git a/src/math/polysat/constraint.h b/src/math/polysat/constraint.h index 2c63f9231..c5ce2c2aa 100644 --- a/src/math/polysat/constraint.h +++ b/src/math/polysat/constraint.h @@ -17,7 +17,6 @@ Author: #include "math/polysat/interval.h" #include "math/polysat/assignment.h" #include "math/polysat/univariate/univariate_solver.h" -#include "util/tbv.h" #include namespace polysat { diff --git a/src/math/polysat/constraint_manager.cpp b/src/math/polysat/constraint_manager.cpp index 4a4fc03b6..cdd4d802d 100644 --- a/src/math/polysat/constraint_manager.cpp +++ b/src/math/polysat/constraint_manager.cpp @@ -596,6 +596,9 @@ namespace polysat { rational q = mod2k(machine_div2k(p.val(), lo), hi - lo + 1); return p.manager().mk_val(q); } + if (lo == hi) { + // could turn it into a single-bit constraint... unclear if that is useful + } if (!lo) { // TODO: we could push the extract down into variables of the term instead of introducing a name. } @@ -637,6 +640,22 @@ namespace polysat { return s.var(v); } + pdd constraint_manager::zero_ext(pdd const& p, unsigned bit_width) { + SASSERT(bit_width > p.power_of_2()); + pdd const q = s.var(s.m_names.mk_name(p)); + constraint_dedup::zext_args args = {q.var(), bit_width}; + auto it = m_dedup.m_zext_expr.find_iterator(args); + if (it != m_dedup.m_zext_expr.end()) + return s.var(it->m_value); + pdd const v = s.var(s.add_var(bit_width)); + m_dedup.m_zext_expr.insert(args, v.var()); + // v[|p|-1:0] = p + s.add_eq(q, extract(v, p.power_of_2() - 1, 0)); + // v < 2^|p| + s.add_ule(q, p.manager().max_value()); + return v; + } + /** unsigned quotient/remainder */ std::pair constraint_manager::div_rem_op_constraint(pdd const& a, pdd const& b) { auto& m = a.manager(); diff --git a/src/math/polysat/constraint_manager.h b/src/math/polysat/constraint_manager.h index c6caaf6de..dd189aebd 100644 --- a/src/math/polysat/constraint_manager.h +++ b/src/math/polysat/constraint_manager.h @@ -41,6 +41,16 @@ namespace polysat { using quot_rem_expr_map = map, quot_rem_args_hash, quot_rem_args_eq>; quot_rem_expr_map m_quot_rem_expr; vector> m_div_rem_list; + + using zext_args = std::pair; + using zext_args_eq = default_eq; + struct zext_args_hash { + unsigned operator()(zext_args const& args) const { + return combine_hash(args.first, args.second); + } + }; + using zext_expr_map = map; + zext_expr_map m_zext_expr; }; // Manage constraint lifetime, deduplication, and connection to boolean variables/literals. @@ -161,6 +171,8 @@ namespace polysat { pdd concat(pdd const& p, pdd const& q); pdd concat(unsigned num_args, pdd const* args); + pdd zero_ext(pdd const& p, unsigned bit_width); + constraint* const* begin() const { return m_constraints.data(); } constraint* const* end() const { return m_constraints.data() + m_constraints.size(); } diff --git a/src/math/polysat/solver.h b/src/math/polysat/solver.h index f7e6ed48f..043f68811 100644 --- a/src/math/polysat/solver.h +++ b/src/math/polysat/solver.h @@ -418,6 +418,9 @@ namespace polysat { /** Create expression for concatenation of args */ pdd concat(unsigned num_args, pdd const* args) { return m_constraints.concat(num_args, args); } + /** Create expression for zero-extension of p */ + pdd zero_ext(pdd const& p, unsigned bit_width) { return m_constraints.zero_ext(p, bit_width); } + /** * Create terms for unsigned quot-rem * diff --git a/src/sat/smt/bv_polysat.cpp b/src/sat/smt/bv_polysat.cpp index b07b6315c..a76bfcddf 100644 --- a/src/sat/smt/bv_polysat.cpp +++ b/src/sat/smt/bv_polysat.cpp @@ -93,7 +93,7 @@ namespace bv { case OP_EXTRACT: polysat_extract(a); break; case OP_CONCAT: polysat_concat(a); break; - case OP_ZERO_EXT: + case OP_ZERO_EXT: polysat_zero_ext(a); break; case OP_SIGN_EXT: // polysat::solver should also support at least: @@ -197,6 +197,13 @@ namespace bv { polysat_set(e, p); } + void solver::polysat_zero_ext(app* e) { + pdd const arg = expr2pdd(e->get_arg(0)); + unsigned const sz = e->get_parameter(0).get_int(); + pdd const p = m_polysat.zero_ext(p, sz); + polysat_set(e, p); + } + void solver::polysat_binary(app* e, std::function const& fn) { SASSERT(e->get_num_args() >= 1); auto p = expr2pdd(e->get_arg(0)); diff --git a/src/sat/smt/bv_solver.h b/src/sat/smt/bv_solver.h index 30fcc9fe4..e4d237ef9 100644 --- a/src/sat/smt/bv_solver.h +++ b/src/sat/smt/bv_solver.h @@ -327,6 +327,7 @@ namespace bv { void polysat_binary(app* e, std::function const& fn); void polysat_extract(app* e); void polysat_concat(app* e); + void polysat_zero_ext(app* e); polysat::pdd expr2pdd(expr* e); void polysat_set(euf::theory_var v, polysat::pdd const& p); polysat::pdd var2pdd(euf::theory_var v);