mirror of
https://github.com/Z3Prover/z3
synced 2025-04-13 04:28:17 +00:00
Merge branch 'master' of https://github.com/Z3Prover/z3 into jfleisher/devIntellitest
This commit is contained in:
commit
4d1362b6a3
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -92,3 +92,4 @@ CMakeSettings.json
|
|||
# Editor temp files
|
||||
*.swp
|
||||
.DS_Store
|
||||
dbg/**
|
||||
|
|
|
@ -1178,7 +1178,7 @@ extern "C" {
|
|||
case OP_BSMOD: return Z3_OP_BSMOD;
|
||||
case OP_BSDIV0: return Z3_OP_BSDIV0;
|
||||
case OP_BUDIV0: return Z3_OP_BUDIV0;
|
||||
case OP_BSREM0: return Z3_OP_BUREM0;
|
||||
case OP_BSREM0: return Z3_OP_BSREM0;
|
||||
case OP_BUREM0: return Z3_OP_BUREM0;
|
||||
case OP_BSMOD0: return Z3_OP_BSMOD0;
|
||||
case OP_ULEQ: return Z3_OP_ULEQ;
|
||||
|
|
|
@ -326,7 +326,9 @@ func_decl * array_decl_plugin::mk_array_ext(unsigned arity, sort * const * domai
|
|||
}
|
||||
sort * r = to_sort(s->get_parameter(i).get_ast());
|
||||
parameter param(i);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
|
||||
func_decl_info info(func_decl_info(m_family_id, OP_ARRAY_EXT, 1, ¶m));
|
||||
info.set_commutative(true);
|
||||
return m_manager->mk_func_decl(m_array_ext_sym, arity, domain, r, info);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -48,6 +48,7 @@ bool decl_collector::is_bool(sort * s) {
|
|||
}
|
||||
|
||||
void decl_collector::visit_func(func_decl * n) {
|
||||
func_decl* g;
|
||||
if (!m_visited.is_marked(n)) {
|
||||
family_id fid = n->get_family_id();
|
||||
if (fid == null_family_id)
|
||||
|
@ -57,6 +58,8 @@ void decl_collector::visit_func(func_decl * n) {
|
|||
recfun::util u(m());
|
||||
m_todo.push_back(u.get_def(n).get_rhs());
|
||||
}
|
||||
else if (m_ar_util.is_as_array(n, g))
|
||||
m_todo.push_back(g);
|
||||
m_visited.mark(n, true);
|
||||
m_trail.push_back(n);
|
||||
}
|
||||
|
@ -65,7 +68,8 @@ void decl_collector::visit_func(func_decl * n) {
|
|||
decl_collector::decl_collector(ast_manager & m):
|
||||
m_manager(m),
|
||||
m_trail(m),
|
||||
m_dt_util(m) {
|
||||
m_dt_util(m),
|
||||
m_ar_util(m) {
|
||||
m_basic_fid = m_manager.get_basic_family_id();
|
||||
m_dt_fid = m_dt_util.get_family_id();
|
||||
recfun::util rec_util(m);
|
||||
|
@ -156,8 +160,15 @@ void decl_collector::collect_deps(sort* s, sort_set& set) {
|
|||
for (unsigned i = 0; i < num_cnstr; i++) {
|
||||
func_decl * cnstr = m_dt_util.get_datatype_constructors(s)->get(i);
|
||||
set.insert(cnstr->get_range());
|
||||
for (unsigned j = 0; j < cnstr->get_arity(); ++j)
|
||||
set.insert(cnstr->get_domain(j));
|
||||
for (unsigned j = 0; j < cnstr->get_arity(); ++j) {
|
||||
sort* n = cnstr->get_domain(j);
|
||||
set.insert(n);
|
||||
for (unsigned i = n->get_num_parameters(); i-- > 0; ) {
|
||||
parameter const& p = n->get_parameter(i);
|
||||
if (p.is_ast() && is_sort(p.get_ast()))
|
||||
set.insert(to_sort(p.get_ast()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -23,6 +23,7 @@ Revision History:
|
|||
#include "util/lim_vector.h"
|
||||
#include "ast/ast.h"
|
||||
#include "ast/datatype_decl_plugin.h"
|
||||
#include "ast/array_decl_plugin.h"
|
||||
|
||||
class decl_collector {
|
||||
ast_manager & m_manager;
|
||||
|
@ -35,6 +36,7 @@ class decl_collector {
|
|||
family_id m_basic_fid;
|
||||
family_id m_dt_fid;
|
||||
datatype_util m_dt_util;
|
||||
array_util m_ar_util;
|
||||
family_id m_rec_fid;
|
||||
ptr_vector<ast> m_todo;
|
||||
|
||||
|
|
|
@ -27,7 +27,9 @@ std::ostream& operator<<(std::ostream& out, opt::ineq_type ie) {
|
|||
case opt::t_eq: return out << " = ";
|
||||
case opt::t_lt: return out << " < ";
|
||||
case opt::t_le: return out << " <= ";
|
||||
case opt::t_divides: return out << " divides ";
|
||||
case opt::t_mod: return out << " mod ";
|
||||
case opt::t_div: return out << " div ";
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -199,7 +201,9 @@ namespace opt {
|
|||
// values satisfy constraints
|
||||
PASSERT(index == 0 || r.m_type != t_lt || r.m_value.is_neg());
|
||||
PASSERT(index == 0 || r.m_type != t_le || !r.m_value.is_pos());
|
||||
PASSERT(index == 0 || r.m_type != t_mod || (mod(r.m_value, r.m_mod).is_zero()));
|
||||
PASSERT(index == 0 || r.m_type != t_divides || (mod(r.m_value, r.m_mod).is_zero()));
|
||||
PASSERT(index == 0 || r.m_type != t_mod || r.m_id < m_var2value.size());
|
||||
PASSERT(index == 0 || r.m_type != t_div || r.m_id < m_var2value.size());
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -454,9 +458,8 @@ namespace opt {
|
|||
}
|
||||
|
||||
rational model_based_opt::row::get_coefficient(unsigned var_id) const {
|
||||
if (m_vars.empty()) {
|
||||
if (m_vars.empty())
|
||||
return rational::zero();
|
||||
}
|
||||
unsigned lo = 0, hi = m_vars.size();
|
||||
while (lo < hi) {
|
||||
unsigned mid = lo + (hi - lo)/2;
|
||||
|
@ -466,28 +469,23 @@ namespace opt {
|
|||
lo = mid;
|
||||
break;
|
||||
}
|
||||
if (id < var_id) {
|
||||
if (id < var_id)
|
||||
lo = mid + 1;
|
||||
}
|
||||
else {
|
||||
else
|
||||
hi = mid;
|
||||
}
|
||||
}
|
||||
if (lo == m_vars.size()) {
|
||||
if (lo == m_vars.size())
|
||||
return rational::zero();
|
||||
}
|
||||
unsigned id = m_vars[lo].m_id;
|
||||
if (id == var_id) {
|
||||
if (id == var_id)
|
||||
return m_vars[lo].m_coeff;
|
||||
}
|
||||
else {
|
||||
else
|
||||
return rational::zero();
|
||||
}
|
||||
}
|
||||
|
||||
model_based_opt::row& model_based_opt::row::normalize() {
|
||||
#if 0
|
||||
if (m_type == t_mod)
|
||||
if (m_type == t_divides || m_type == t_mod || m_type == t_div)
|
||||
return *this;
|
||||
rational D(denominator(abs(m_coeff)));
|
||||
if (D == 0)
|
||||
|
@ -526,6 +524,9 @@ namespace opt {
|
|||
//
|
||||
// the resolvent is the same in all cases (simpler proof should exist)
|
||||
//
|
||||
// assume a1 < 0, -a1 = a2:
|
||||
// t1 <= a2*div(t2, a2)
|
||||
//
|
||||
|
||||
void model_based_opt::resolve(unsigned row_src, rational const& a1, unsigned row_dst, unsigned x) {
|
||||
|
||||
|
@ -537,7 +538,7 @@ namespace opt {
|
|||
rational a2 = get_coefficient(row_dst, x);
|
||||
if (is_int(x)) {
|
||||
TRACE("opt",
|
||||
tout << a1 << " " << a2 << ": ";
|
||||
tout << x << ": " << a1 << " " << a2 << ": ";
|
||||
display(tout, m_rows[row_dst]);
|
||||
display(tout, m_rows[row_src]););
|
||||
if (a1.is_pos() != a2.is_pos() || m_rows[row_src].m_type == opt::t_eq) {
|
||||
|
@ -547,7 +548,7 @@ namespace opt {
|
|||
mul(row_dst, abs(a1));
|
||||
mul_add(false, row_dst, -abs(a2), row_src);
|
||||
}
|
||||
TRACE("opt", display(tout, m_rows[row_dst]););
|
||||
TRACE("opt", display(tout << "result ", m_rows[row_dst]););
|
||||
normalize(row_dst);
|
||||
}
|
||||
else {
|
||||
|
@ -571,12 +572,13 @@ namespace opt {
|
|||
rational a2 = get_coefficient(row_dst, x);
|
||||
mul(row_dst, a1);
|
||||
mul_add(false, row_dst, -a2, row_src);
|
||||
normalize(row_dst);
|
||||
SASSERT(get_coefficient(row_dst, x).is_zero());
|
||||
}
|
||||
|
||||
// resolution for integer rows.
|
||||
void model_based_opt::mul_add(
|
||||
unsigned x, rational const& src_c, unsigned row_src, rational const& dst_c, unsigned row_dst) {
|
||||
unsigned x, rational src_c, unsigned row_src, rational dst_c, unsigned row_dst) {
|
||||
row& dst = m_rows[row_dst];
|
||||
row const& src = m_rows[row_src];
|
||||
SASSERT(is_int(x));
|
||||
|
@ -593,17 +595,9 @@ namespace opt {
|
|||
rational src_val = src.m_value - x_val*src_c;
|
||||
rational distance = abs_src_c * dst_val + abs_dst_c * src_val + slack;
|
||||
bool use_case1 = distance.is_nonpos() || abs_src_c.is_one() || abs_dst_c.is_one();
|
||||
bool use_case2 = false && abs_src_c == abs_dst_c && src_c.is_pos() != dst_c.is_pos() && !abs_src_c.is_one() && t_le == dst.m_type && t_le == src.m_type;
|
||||
bool use_case3 = false && src_c.is_pos() != dst_c.is_pos() && t_le == dst.m_type && t_le == src.m_type;
|
||||
|
||||
#if 0
|
||||
if (distance.is_nonpos() && !abs_src_c.is_one() && !abs_dst_c.is_one()) {
|
||||
unsigned r = copy_row(row_src);
|
||||
mul_add(false, r, rational::one(), row_dst);
|
||||
del_var(r, x);
|
||||
add(r, slack);
|
||||
TRACE("qe", tout << m_rows[r];);
|
||||
SASSERT(!m_rows[r].m_value.is_pos());
|
||||
}
|
||||
#endif
|
||||
|
||||
if (use_case1) {
|
||||
TRACE("opt", tout << "slack: " << slack << " " << src_c << " " << dst_val << " " << dst_c << " " << src_val << "\n";);
|
||||
|
@ -614,6 +608,54 @@ namespace opt {
|
|||
return;
|
||||
}
|
||||
|
||||
if (use_case2 || use_case3) {
|
||||
// case2:
|
||||
// x*src_c + s <= 0
|
||||
// -x*src_c + t <= 0
|
||||
//
|
||||
// -src_c*div(-s, src_c) + t <= 0
|
||||
//
|
||||
// Example:
|
||||
// t <= 100*x <= s
|
||||
// Then t <= 100*div(s, 100)
|
||||
//
|
||||
// case3:
|
||||
// x*src_c + s <= 0
|
||||
// -x*dst_c + t <= 0
|
||||
// t <= x*dst_c, x*src_c <= -s ->
|
||||
// t <= dst_c*div(-s, src_c) ->
|
||||
// -dst_c*div(-s,src_c) + t <= 0
|
||||
//
|
||||
|
||||
bool swapped = false;
|
||||
if (src_c < 0) {
|
||||
std::swap(row_src, row_dst);
|
||||
std::swap(src_c, dst_c);
|
||||
std::swap(abs_src_c, abs_dst_c);
|
||||
swapped = true;
|
||||
}
|
||||
vector<var> src_coeffs, dst_coeffs;
|
||||
rational src_coeff = m_rows[row_src].m_coeff;
|
||||
rational dst_coeff = m_rows[row_dst].m_coeff;
|
||||
for (auto const& v : m_rows[row_src].m_vars)
|
||||
if (v.m_id != x)
|
||||
src_coeffs.push_back(var(v.m_id, -v.m_coeff));
|
||||
for (auto const& v : m_rows[row_dst].m_vars)
|
||||
if (v.m_id != x)
|
||||
dst_coeffs.push_back(v);
|
||||
unsigned v = UINT_MAX;
|
||||
if (src_coeffs.empty())
|
||||
dst_coeff -= abs_dst_c*div(-src_coeff, abs_src_c);
|
||||
else
|
||||
v = add_div(src_coeffs, -src_coeff, abs_src_c);
|
||||
if (v != UINT_MAX) dst_coeffs.push_back(var(v, -abs_dst_c));
|
||||
if (swapped)
|
||||
std::swap(row_src, row_dst);
|
||||
retire_row(row_dst);
|
||||
add_constraint(dst_coeffs, dst_coeff, t_le);
|
||||
return;
|
||||
}
|
||||
|
||||
//
|
||||
// create finite disjunction for |b|.
|
||||
// exists x, z in [0 .. |b|-2] . b*x + s + z = 0 && ax + t <= 0 && bx + s <= 0
|
||||
|
@ -669,12 +711,14 @@ namespace opt {
|
|||
}
|
||||
|
||||
void model_based_opt::mul(unsigned dst, rational const& c) {
|
||||
if (c.is_one()) return;
|
||||
if (c.is_one())
|
||||
return;
|
||||
row& r = m_rows[dst];
|
||||
for (auto & v : r.m_vars) {
|
||||
for (auto & v : r.m_vars)
|
||||
v.m_coeff *= c;
|
||||
}
|
||||
r.m_mod *= c;
|
||||
r.m_coeff *= c;
|
||||
if (r.m_type != t_div && r.m_type != t_mod)
|
||||
r.m_value *= c;
|
||||
}
|
||||
|
||||
|
@ -690,28 +734,18 @@ namespace opt {
|
|||
r.m_value -= c;
|
||||
}
|
||||
|
||||
void model_based_opt::del_var(unsigned dst, unsigned x) {
|
||||
row& r = m_rows[dst];
|
||||
unsigned j = 0;
|
||||
for (var & v : r.m_vars) {
|
||||
if (v.m_id == x) {
|
||||
r.m_value -= eval(x)*r.m_coeff;
|
||||
}
|
||||
else {
|
||||
r.m_vars[j++] = v;
|
||||
}
|
||||
}
|
||||
r.m_vars.shrink(j);
|
||||
}
|
||||
|
||||
|
||||
void model_based_opt::normalize(unsigned row_id) {
|
||||
row& r = m_rows[row_id];
|
||||
if (r.m_vars.empty()) {
|
||||
retire_row(row_id);
|
||||
return;
|
||||
}
|
||||
if (r.m_type == t_mod) return;
|
||||
if (r.m_type == t_divides)
|
||||
return;
|
||||
if (r.m_type == t_mod)
|
||||
return;
|
||||
if (r.m_type == t_div)
|
||||
return;
|
||||
rational g(abs(r.m_vars[0].m_coeff));
|
||||
bool all_int = g.is_int();
|
||||
for (unsigned i = 1; all_int && !g.is_one() && i < r.m_vars.size(); ++i) {
|
||||
|
@ -741,9 +775,9 @@ namespace opt {
|
|||
// set row1 <- row1 + c*row2
|
||||
//
|
||||
void model_based_opt::mul_add(bool same_sign, unsigned row_id1, rational const& c, unsigned row_id2) {
|
||||
if (c.is_zero()) {
|
||||
if (c.is_zero())
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
m_new_vars.reset();
|
||||
row& r1 = m_rows[row_id1];
|
||||
|
@ -758,10 +792,9 @@ namespace opt {
|
|||
for (; j < r2.m_vars.size(); ++j) {
|
||||
m_new_vars.push_back(r2.m_vars[j]);
|
||||
m_new_vars.back().m_coeff *= c;
|
||||
if (row_id1 != m_objective_id) {
|
||||
if (row_id1 != m_objective_id)
|
||||
m_var2row_ids[r2.m_vars[j].m_id].push_back(row_id1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -772,10 +805,9 @@ namespace opt {
|
|||
m_new_vars.back().m_coeff += c*r2.m_vars[j].m_coeff;
|
||||
++i;
|
||||
++j;
|
||||
if (m_new_vars.back().m_coeff.is_zero()) {
|
||||
if (m_new_vars.back().m_coeff.is_zero())
|
||||
m_new_vars.pop_back();
|
||||
}
|
||||
}
|
||||
else if (v1 < v2) {
|
||||
m_new_vars.push_back(r1.m_vars[i]);
|
||||
++i;
|
||||
|
@ -783,9 +815,8 @@ namespace opt {
|
|||
else {
|
||||
m_new_vars.push_back(r2.m_vars[j]);
|
||||
m_new_vars.back().m_coeff *= c;
|
||||
if (row_id1 != m_objective_id) {
|
||||
if (row_id1 != m_objective_id)
|
||||
m_var2row_ids[r2.m_vars[j].m_id].push_back(row_id1);
|
||||
}
|
||||
++j;
|
||||
}
|
||||
}
|
||||
|
@ -793,25 +824,21 @@ namespace opt {
|
|||
r1.m_vars.swap(m_new_vars);
|
||||
r1.m_value += c*r2.m_value;
|
||||
|
||||
if (!same_sign && r2.m_type == t_lt) {
|
||||
if (!same_sign && r2.m_type == t_lt)
|
||||
r1.m_type = t_lt;
|
||||
}
|
||||
else if (same_sign && r1.m_type == t_lt && r2.m_type == t_lt) {
|
||||
else if (same_sign && r1.m_type == t_lt && r2.m_type == t_lt)
|
||||
r1.m_type = t_le;
|
||||
}
|
||||
SASSERT(invariant(row_id1, r1));
|
||||
}
|
||||
|
||||
void model_based_opt::display(std::ostream& out) const {
|
||||
for (auto const& r : m_rows) {
|
||||
for (auto const& r : m_rows)
|
||||
display(out, r);
|
||||
}
|
||||
for (unsigned i = 0; i < m_var2row_ids.size(); ++i) {
|
||||
unsigned_vector const& rows = m_var2row_ids[i];
|
||||
out << i << ": ";
|
||||
for (auto const& r : rows) {
|
||||
for (auto const& r : rows)
|
||||
out << r << " ";
|
||||
}
|
||||
out << "\n";
|
||||
}
|
||||
}
|
||||
|
@ -819,33 +846,36 @@ namespace opt {
|
|||
void model_based_opt::display(std::ostream& out, vector<var> const& vars, rational const& coeff) {
|
||||
unsigned i = 0;
|
||||
for (var const& v : vars) {
|
||||
if (i > 0 && v.m_coeff.is_pos()) {
|
||||
if (i > 0 && v.m_coeff.is_pos())
|
||||
out << "+ ";
|
||||
}
|
||||
++i;
|
||||
if (v.m_coeff.is_one()) {
|
||||
if (v.m_coeff.is_one())
|
||||
out << "v" << v.m_id << " ";
|
||||
}
|
||||
else {
|
||||
else
|
||||
out << v.m_coeff << "*v" << v.m_id << " ";
|
||||
}
|
||||
}
|
||||
if (coeff.is_pos()) {
|
||||
if (coeff.is_pos())
|
||||
out << " + " << coeff << " ";
|
||||
}
|
||||
else if (coeff.is_neg()) {
|
||||
else if (coeff.is_neg())
|
||||
out << coeff << " ";
|
||||
}
|
||||
}
|
||||
|
||||
std::ostream& model_based_opt::display(std::ostream& out, row const& r) {
|
||||
out << (r.m_alive?"a":"d") << " ";
|
||||
display(out, r.m_vars, r.m_coeff);
|
||||
if (r.m_type == opt::t_mod) {
|
||||
switch (r.m_type) {
|
||||
case opt::t_divides:
|
||||
out << r.m_type << " " << r.m_mod << " = 0; value: " << r.m_value << "\n";
|
||||
}
|
||||
else {
|
||||
break;
|
||||
case opt::t_mod:
|
||||
out << r.m_type << " " << r.m_mod << " = v" << r.m_id << " ; mod: " << mod(r.m_value, r.m_mod) << "\n";
|
||||
break;
|
||||
case opt::t_div:
|
||||
out << r.m_type << " " << r.m_mod << " = v" << r.m_id << " ; div: " << div(r.m_value, r.m_mod) << "\n";
|
||||
break;
|
||||
default:
|
||||
out << r.m_type << " 0; value: " << r.m_value << "\n";
|
||||
break;
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
@ -910,32 +940,72 @@ namespace opt {
|
|||
return row_id;
|
||||
}
|
||||
|
||||
unsigned model_based_opt::copy_row(unsigned src) {
|
||||
unsigned model_based_opt::copy_row(unsigned src, unsigned excl) {
|
||||
unsigned dst = new_row();
|
||||
row const& r = m_rows[src];
|
||||
set_row(dst, r.m_vars, r.m_coeff, r.m_mod, r.m_type);
|
||||
for (auto const& v : r.m_vars) {
|
||||
if (v.m_id != excl)
|
||||
m_var2row_ids[v.m_id].push_back(dst);
|
||||
}
|
||||
SASSERT(invariant(dst, m_rows[dst]));
|
||||
return dst;
|
||||
}
|
||||
|
||||
void model_based_opt::add_lower_bound(unsigned x, rational const& lo) {
|
||||
vector<var> coeffs;
|
||||
coeffs.push_back(var(x, rational::minus_one()));
|
||||
add_constraint(coeffs, lo, t_le);
|
||||
}
|
||||
|
||||
void model_based_opt::add_upper_bound(unsigned x, rational const& hi) {
|
||||
vector<var> coeffs;
|
||||
coeffs.push_back(var(x, rational::one()));
|
||||
add_constraint(coeffs, -hi, t_le);
|
||||
}
|
||||
|
||||
void model_based_opt::add_constraint(vector<var> const& coeffs, rational const& c, ineq_type rel) {
|
||||
add_constraint(coeffs, c, rational::zero(), rel);
|
||||
add_constraint(coeffs, c, rational::zero(), rel, 0);
|
||||
}
|
||||
|
||||
void model_based_opt::add_divides(vector<var> const& coeffs, rational const& c, rational const& m) {
|
||||
add_constraint(coeffs, c, m, t_mod);
|
||||
rational g(c);
|
||||
for (auto const& [v, coeff] : coeffs)
|
||||
g = gcd(coeff, g);
|
||||
if ((g/m).is_int())
|
||||
return;
|
||||
add_constraint(coeffs, c, m, t_divides, 0);
|
||||
}
|
||||
|
||||
void model_based_opt::add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel) {
|
||||
unsigned model_based_opt::add_mod(vector<var> const& coeffs, rational const& c, rational const& m) {
|
||||
rational value = c;
|
||||
for (auto const& var : coeffs)
|
||||
value += var.m_coeff * m_var2value[var.m_id];
|
||||
unsigned v = add_var(mod(value, m), true);
|
||||
add_constraint(coeffs, c, m, t_mod, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
unsigned model_based_opt::add_div(vector<var> const& coeffs, rational const& c, rational const& m) {
|
||||
rational value = c;
|
||||
for (auto const& var : coeffs)
|
||||
value += var.m_coeff * m_var2value[var.m_id];
|
||||
unsigned v = add_var(div(value, m), true);
|
||||
add_constraint(coeffs, c, m, t_div, v);
|
||||
return v;
|
||||
}
|
||||
|
||||
void model_based_opt::add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel, unsigned id) {
|
||||
auto const& r = m_rows.back();
|
||||
if (r.m_vars == coeffs && r.m_coeff == c && r.m_mod == m && r.m_type == rel && r.m_id == id && r.m_alive)
|
||||
return;
|
||||
unsigned row_id = new_row();
|
||||
set_row(row_id, coeffs, c, m, rel);
|
||||
for (var const& coeff : coeffs) {
|
||||
m_rows[row_id].m_id = id;
|
||||
for (var const& coeff : coeffs)
|
||||
m_var2row_ids[coeff.m_id].push_back(row_id);
|
||||
}
|
||||
SASSERT(invariant(row_id, m_rows[row_id]));
|
||||
normalize(row_id);
|
||||
}
|
||||
|
||||
void model_based_opt::set_objective(vector<var> const& coeffs, rational const& c) {
|
||||
|
@ -943,12 +1013,10 @@ namespace opt {
|
|||
}
|
||||
|
||||
void model_based_opt::get_live_rows(vector<row>& rows) {
|
||||
for (row & r : m_rows) {
|
||||
if (r.m_alive) {
|
||||
for (row & r : m_rows)
|
||||
if (r.m_alive)
|
||||
rows.push_back(r.normalize());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// pick glb and lub representative.
|
||||
|
@ -971,7 +1039,9 @@ namespace opt {
|
|||
model_based_opt::def model_based_opt::project(unsigned x, bool compute_def) {
|
||||
unsigned_vector& lub_rows = m_lub;
|
||||
unsigned_vector& glb_rows = m_glb;
|
||||
unsigned_vector& divide_rows = m_divides;
|
||||
unsigned_vector& mod_rows = m_mod;
|
||||
unsigned_vector& div_rows = m_div;
|
||||
unsigned lub_index = UINT_MAX, glb_index = UINT_MAX;
|
||||
bool lub_strict = false, glb_strict = false;
|
||||
rational lub_val, glb_val;
|
||||
|
@ -980,7 +1050,9 @@ namespace opt {
|
|||
uint_set visited;
|
||||
lub_rows.reset();
|
||||
glb_rows.reset();
|
||||
divide_rows.reset();
|
||||
mod_rows.reset();
|
||||
div_rows.reset();
|
||||
bool lub_is_unit = true, glb_is_unit = true;
|
||||
unsigned eq_row = UINT_MAX;
|
||||
// select the lub and glb.
|
||||
|
@ -1001,9 +1073,12 @@ namespace opt {
|
|||
eq_row = row_id;
|
||||
continue;
|
||||
}
|
||||
if (r.m_type == t_mod) {
|
||||
if (r.m_type == t_mod)
|
||||
mod_rows.push_back(row_id);
|
||||
}
|
||||
else if (r.m_type == t_div)
|
||||
div_rows.push_back(row_id);
|
||||
else if (r.m_type == t_divides)
|
||||
divide_rows.push_back(row_id);
|
||||
else if (a.is_pos()) {
|
||||
rational lub_value = x_val - (r.m_value/a);
|
||||
if (lub_rows.empty() ||
|
||||
|
@ -1031,13 +1106,17 @@ namespace opt {
|
|||
}
|
||||
}
|
||||
|
||||
if (!mod_rows.empty()) {
|
||||
if (!mod_rows.empty())
|
||||
return solve_mod(x, mod_rows, compute_def);
|
||||
}
|
||||
|
||||
if (eq_row != UINT_MAX) {
|
||||
if (!div_rows.empty())
|
||||
return solve_div(x, div_rows, compute_def);
|
||||
|
||||
if (!divide_rows.empty())
|
||||
return solve_divides(x, divide_rows, compute_def);
|
||||
|
||||
if (eq_row != UINT_MAX)
|
||||
return solve_for(eq_row, x, compute_def);
|
||||
}
|
||||
|
||||
def result;
|
||||
unsigned lub_size = lub_rows.size();
|
||||
|
@ -1047,15 +1126,12 @@ namespace opt {
|
|||
// There are only upper or only lower bounds.
|
||||
if (row_index == UINT_MAX) {
|
||||
if (compute_def) {
|
||||
if (lub_index != UINT_MAX) {
|
||||
if (lub_index != UINT_MAX)
|
||||
result = solve_for(lub_index, x, true);
|
||||
}
|
||||
else if (glb_index != UINT_MAX) {
|
||||
else if (glb_index != UINT_MAX)
|
||||
result = solve_for(glb_index, x, true);
|
||||
}
|
||||
else {
|
||||
else
|
||||
result = def() + m_var2value[x];
|
||||
}
|
||||
SASSERT(eval(result) == eval(x));
|
||||
}
|
||||
else {
|
||||
|
@ -1068,13 +1144,11 @@ namespace opt {
|
|||
SASSERT(lub_index != UINT_MAX);
|
||||
SASSERT(glb_index != UINT_MAX);
|
||||
if (compute_def) {
|
||||
if (lub_size <= glb_size) {
|
||||
if (lub_size <= glb_size)
|
||||
result = def(m_rows[lub_index], x);
|
||||
}
|
||||
else {
|
||||
else
|
||||
result = def(m_rows[glb_index], x);
|
||||
}
|
||||
}
|
||||
|
||||
// The number of matching lower and upper bounds is small.
|
||||
if ((lub_size <= 2 || glb_size <= 2) &&
|
||||
|
@ -1094,27 +1168,286 @@ namespace opt {
|
|||
}
|
||||
}
|
||||
}
|
||||
for (unsigned row_id : lub_rows) retire_row(row_id);
|
||||
for (unsigned row_id : lub_rows)
|
||||
retire_row(row_id);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// General case.
|
||||
rational coeff = get_coefficient(row_index, x);
|
||||
for (unsigned row_id : lub_rows) {
|
||||
if (row_id != row_index) {
|
||||
|
||||
for (unsigned row_id : lub_rows)
|
||||
if (row_id != row_index)
|
||||
resolve(row_index, coeff, row_id, x);
|
||||
}
|
||||
}
|
||||
for (unsigned row_id : glb_rows) {
|
||||
if (row_id != row_index) {
|
||||
|
||||
for (unsigned row_id : glb_rows)
|
||||
if (row_id != row_index)
|
||||
resolve(row_index, coeff, row_id, x);
|
||||
}
|
||||
}
|
||||
retire_row(row_index);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
//
|
||||
// Given v = a*x + b mod K
|
||||
//
|
||||
// - remove v = a*x + b mod K
|
||||
//
|
||||
// case a = 1:
|
||||
// - add w = b mod K
|
||||
// - x |-> K*y + z, 0 <= z < K
|
||||
// - if z.value + w.value < K:
|
||||
// add z + w - v = 0
|
||||
// - if z.value + w.value >= K:
|
||||
// add z + w - v - K = 0
|
||||
//
|
||||
// case a != 1, gcd(a, K) = 1
|
||||
// - x |-> x*y + a^-1*z, 0 <= z < K
|
||||
// - add w = b mod K
|
||||
// if z.value + w.value < K
|
||||
// add z + w - v = 0
|
||||
// if z.value + w.value >= K
|
||||
// add z + w - v - K = 0
|
||||
//
|
||||
// case a != 1, gcd(a,K) = g != 1
|
||||
// - x |-> x*y + a^-1*z, 0 <= z < K
|
||||
// a*x + b mod K = v is now
|
||||
// g*z + b mod K = v
|
||||
// - add w = b mod K
|
||||
// - 0 <= g*z.value + w.value < K*(g+1)
|
||||
// - add g*z + w - v - k*K = 0 for suitable k from 0 .. g based on model
|
||||
//
|
||||
|
||||
model_based_opt::def model_based_opt::solve_mod(unsigned x, unsigned_vector const& _mod_rows, bool compute_def) {
|
||||
def result;
|
||||
unsigned_vector mod_rows(_mod_rows);
|
||||
rational K(1);
|
||||
for (unsigned ri : mod_rows)
|
||||
K = lcm(K, m_rows[ri].m_mod);
|
||||
|
||||
rational x_value = m_var2value[x];
|
||||
rational y_value = div(x_value, K);
|
||||
rational z_value = mod(x_value, K);
|
||||
SASSERT(x_value == K * y_value + z_value);
|
||||
SASSERT(0 <= z_value && z_value < K);
|
||||
// add new variables
|
||||
unsigned z = add_var(z_value, true);
|
||||
unsigned y = add_var(y_value, true);
|
||||
|
||||
uint_set visited;
|
||||
for (unsigned ri : mod_rows) {
|
||||
m_rows[ri].m_alive = false;
|
||||
visited.insert(ri);
|
||||
}
|
||||
|
||||
// replace x by K*y + z in other rows.
|
||||
for (unsigned ri : m_var2row_ids[x]) {
|
||||
if (visited.contains(ri))
|
||||
continue;
|
||||
replace_var(ri, x, K, y, rational::one(), z);
|
||||
visited.insert(ri);
|
||||
normalize(ri);
|
||||
}
|
||||
|
||||
// add bounds for z
|
||||
add_lower_bound(z, rational::zero());
|
||||
add_upper_bound(z, K - 1);
|
||||
|
||||
for (unsigned ri : mod_rows) {
|
||||
rational a = get_coefficient(ri, x);
|
||||
// add w = b mod K
|
||||
vector<var> coeffs = m_rows[ri].m_vars;
|
||||
rational coeff = m_rows[ri].m_coeff;
|
||||
unsigned v = m_rows[ri].m_id;
|
||||
|
||||
unsigned w = UINT_MAX;
|
||||
rational offset(0);
|
||||
if (coeffs.empty())
|
||||
offset = mod(coeff, K);
|
||||
else
|
||||
w = add_mod(coeffs, coeff, K);
|
||||
|
||||
rational w_value = w == UINT_MAX ? offset : m_var2value[w];
|
||||
|
||||
// add v = a*z + w - k*K = 0, for k = (a*z_value + w_value) div K
|
||||
// claim: (= (mod x K) (- x (* K (div x K)))))) is a theorem for every x, K != 0
|
||||
rational kK = div(a * z_value + w_value, K) * K;
|
||||
vector<var> mod_coeffs;
|
||||
mod_coeffs.push_back(var(v, rational::minus_one()));
|
||||
mod_coeffs.push_back(var(z, a));
|
||||
if (w != UINT_MAX) mod_coeffs.push_back(var(w, rational::one()));
|
||||
add_constraint(mod_coeffs, kK + offset, t_eq);
|
||||
add_lower_bound(v, rational::zero());
|
||||
add_upper_bound(v, K - 1);
|
||||
|
||||
// allow to recycle row.
|
||||
m_retired_rows.push_back(ri);
|
||||
|
||||
project(v, false);
|
||||
}
|
||||
|
||||
def y_def = project(y, compute_def);
|
||||
def z_def = project(z, compute_def);
|
||||
|
||||
if (compute_def) {
|
||||
result = (y_def * K) + z_def;
|
||||
m_var2value[x] = eval(result);
|
||||
}
|
||||
TRACE("opt", display(tout << "solve_mod\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// Given v = a*x + b div K
|
||||
// Replace x |-> K*y + z
|
||||
// - w = b div K
|
||||
// - v = ((a*K*y + a*z) + b) div K
|
||||
// = a*y + (a*z + b) div K
|
||||
// = a*y + b div K + (b mod K + a*z) div K
|
||||
// = a*y + b div K + k
|
||||
// where k := (b.value mod K + a*z.value) div K
|
||||
// k is between 0 and a
|
||||
//
|
||||
// - k*K <= b mod K + a*z < (k+1)*K
|
||||
//
|
||||
// A better version using a^-1
|
||||
// - v = (a*K*y + a^-1*a*z + b) div K
|
||||
// = a*y + ((K*A + g)*z + b) div K where we write a*a^-1 = K*A + g
|
||||
// = a*y + A + (g*z + b) div K
|
||||
// - k*K <= b Kod m + gz < (k+1)*K
|
||||
// where k is between 0 and g
|
||||
// when gcd(a, K) = 1, then there are only two cases.
|
||||
//
|
||||
model_based_opt::def model_based_opt::solve_div(unsigned x, unsigned_vector const& _div_rows, bool compute_def) {
|
||||
def result;
|
||||
unsigned_vector div_rows(_div_rows);
|
||||
SASSERT(!div_rows.empty());
|
||||
|
||||
rational K(1);
|
||||
for (unsigned ri : div_rows)
|
||||
K = lcm(K, m_rows[ri].m_mod);
|
||||
|
||||
rational x_value = m_var2value[x];
|
||||
rational z_value = mod(x_value, K);
|
||||
rational y_value = div(x_value, K);
|
||||
SASSERT(x_value == K * y_value + z_value);
|
||||
SASSERT(0 <= z_value && z_value < K);
|
||||
// add new variables
|
||||
unsigned z = add_var(z_value, true);
|
||||
unsigned y = add_var(y_value, true);
|
||||
|
||||
uint_set visited;
|
||||
for (unsigned ri : div_rows) {
|
||||
row& r = m_rows[ri];
|
||||
mul(ri, K / r.m_mod);
|
||||
r.m_alive = false;
|
||||
visited.insert(ri);
|
||||
}
|
||||
|
||||
// replace x by K*y + z in other rows.
|
||||
for (unsigned ri : m_var2row_ids[x]) {
|
||||
if (visited.contains(ri))
|
||||
continue;
|
||||
replace_var(ri, x, K, y, rational::one(), z);
|
||||
visited.insert(ri);
|
||||
normalize(ri);
|
||||
}
|
||||
|
||||
// add bounds for z
|
||||
add_lower_bound(z, rational::zero());
|
||||
add_upper_bound(z, K - 1);
|
||||
|
||||
TRACE("opt", display(tout));
|
||||
|
||||
// solve for x_value = K*y_value + z_value, 0 <= z_value < K.
|
||||
|
||||
for (unsigned ri : div_rows) {
|
||||
|
||||
rational a = get_coefficient(ri, x);
|
||||
replace_var(ri, x, rational::zero());
|
||||
|
||||
// add w = b div m
|
||||
vector<var> coeffs = m_rows[ri].m_vars;
|
||||
rational coeff = m_rows[ri].m_coeff;
|
||||
unsigned w = UINT_MAX;
|
||||
rational offset(0);
|
||||
if (coeffs.empty())
|
||||
offset = div(coeff, K);
|
||||
else
|
||||
w = add_div(coeffs, coeff, K);
|
||||
|
||||
//
|
||||
// w = b div K
|
||||
// v = a*y + w + k
|
||||
// k = (a*z_value + (b_value mod K)) div K
|
||||
// k*K <= a*z + b mod K < (k+1)*K
|
||||
//
|
||||
/**
|
||||
* It is based on the following claim (tested for select values of a, K)
|
||||
* (define-const K Int 13)
|
||||
* (declare-const b Int)
|
||||
* (define-const a Int -11)
|
||||
* (declare-const y Int)
|
||||
* (declare-const z Int)
|
||||
* (define-const w Int (div b K))
|
||||
* (define-const k1 Int (+ (* a z) (mod b K)))
|
||||
* (define-const k Int (div k1 K))
|
||||
* (define-const x Int (+ (* K y) z))
|
||||
* (define-const u Int (+ (* a x) b))
|
||||
* (define-const v Int (+ (* a y) w k))
|
||||
* (assert (<= 0 z))
|
||||
* (assert (< z K))
|
||||
* (assert (<= (* K k) k1))
|
||||
* (assert (< k1 (* K (+ k 1))))
|
||||
* (assert (not (= (div u K) v)))
|
||||
* (check-sat)
|
||||
*/
|
||||
unsigned v = m_rows[ri].m_id;
|
||||
rational b_value = eval(coeffs) + coeff;
|
||||
rational k = div(a * z_value + mod(b_value, K), K);
|
||||
vector<var> div_coeffs;
|
||||
div_coeffs.push_back(var(v, rational::minus_one()));
|
||||
div_coeffs.push_back(var(y, a));
|
||||
if (w != UINT_MAX) div_coeffs.push_back(var(w, rational::one()));
|
||||
add_constraint(div_coeffs, k + offset, t_eq);
|
||||
|
||||
unsigned u = UINT_MAX;
|
||||
offset = 0;
|
||||
if (coeffs.empty())
|
||||
offset = mod(coeff, K);
|
||||
else
|
||||
u = add_mod(coeffs, coeff, K);
|
||||
|
||||
// add a*z + (b mod K) < (k + 1)*K
|
||||
vector<var> bound_coeffs;
|
||||
bound_coeffs.push_back(var(z, a));
|
||||
if (u != UINT_MAX) bound_coeffs.push_back(var(u, rational::one()));
|
||||
add_constraint(bound_coeffs, 1 - K * (k + 1) + offset, t_le);
|
||||
|
||||
// add k*K <= az + (b mod K)
|
||||
for (auto& c : bound_coeffs)
|
||||
c.m_coeff.neg();
|
||||
add_constraint(bound_coeffs, k * K - offset, t_le);
|
||||
// allow to recycle row.
|
||||
m_retired_rows.push_back(ri);
|
||||
project(v, false);
|
||||
}
|
||||
|
||||
TRACE("opt", display(tout << "solve_div reduced " << y << " " << z << "\n"));
|
||||
// project internal variables.
|
||||
|
||||
def y_def = project(y, compute_def);
|
||||
def z_def = project(z, compute_def);
|
||||
|
||||
if (compute_def) {
|
||||
result = (y_def * K) + z_def;
|
||||
m_var2value[x] = eval(result);
|
||||
}
|
||||
TRACE("opt", display(tout << "solve_div done v" << x << "\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
//
|
||||
// compute D and u.
|
||||
//
|
||||
|
@ -1130,10 +1463,10 @@ namespace opt {
|
|||
// x := D*x' + u
|
||||
//
|
||||
|
||||
model_based_opt::def model_based_opt::solve_mod(unsigned x, unsigned_vector const& mod_rows, bool compute_def) {
|
||||
SASSERT(!mod_rows.empty());
|
||||
model_based_opt::def model_based_opt::solve_divides(unsigned x, unsigned_vector const& divide_rows, bool compute_def) {
|
||||
SASSERT(!divide_rows.empty());
|
||||
rational D(1);
|
||||
for (unsigned idx : mod_rows) {
|
||||
for (unsigned idx : divide_rows) {
|
||||
D = lcm(D, m_rows[idx].m_mod);
|
||||
}
|
||||
if (D.is_zero()) {
|
||||
|
@ -1144,7 +1477,7 @@ namespace opt {
|
|||
rational val_x = m_var2value[x];
|
||||
rational u = mod(val_x, D);
|
||||
SASSERT(u.is_nonneg() && u < D);
|
||||
for (unsigned idx : mod_rows) {
|
||||
for (unsigned idx : divide_rows) {
|
||||
replace_var(idx, x, u);
|
||||
SASSERT(invariant(idx, m_rows[idx]));
|
||||
normalize(idx);
|
||||
|
@ -1217,18 +1550,35 @@ namespace opt {
|
|||
replace_var(row_id, x, B);
|
||||
r.m_vars.push_back(var(y, coeff*A));
|
||||
r.m_value += coeff*A*m_var2value[y];
|
||||
if (!r.m_vars.empty() && r.m_vars.back().m_id > y) {
|
||||
if (!r.m_vars.empty() && r.m_vars.back().m_id > y)
|
||||
std::sort(r.m_vars.begin(), r.m_vars.end(), var::compare());
|
||||
}
|
||||
m_var2row_ids[y].push_back(row_id);
|
||||
SASSERT(invariant(row_id, r));
|
||||
}
|
||||
|
||||
// update row with: x |-> A*y + B*z
|
||||
void model_based_opt::replace_var(unsigned row_id, unsigned x, rational const& A, unsigned y, rational const& B, unsigned z) {
|
||||
row& r = m_rows[row_id];
|
||||
rational coeff = get_coefficient(row_id, x);
|
||||
if (coeff.is_zero() || !r.m_alive)
|
||||
return;
|
||||
replace_var(row_id, x, rational::zero());
|
||||
if (A != 0) r.m_vars.push_back(var(y, coeff*A));
|
||||
if (B != 0) r.m_vars.push_back(var(z, coeff*B));
|
||||
r.m_value += coeff*A*m_var2value[y];
|
||||
r.m_value += coeff*B*m_var2value[z];
|
||||
std::sort(r.m_vars.begin(), r.m_vars.end(), var::compare());
|
||||
if (A != 0) m_var2row_ids[y].push_back(row_id);
|
||||
if (B != 0) m_var2row_ids[z].push_back(row_id);
|
||||
SASSERT(invariant(row_id, r));
|
||||
}
|
||||
|
||||
// 3x + t = 0 & 7 | (c*x + s) & ax <= u
|
||||
// 3 | -t & 21 | (-ct + 3s) & a-t <= 3u
|
||||
|
||||
model_based_opt::def model_based_opt::solve_for(unsigned row_id1, unsigned x, bool compute_def) {
|
||||
TRACE("opt", tout << "v" << x << " := " << eval(x) << "\n" << m_rows[row_id1] << "\n";);
|
||||
TRACE("opt", tout << "v" << x << " := " << eval(x) << "\n" << m_rows[row_id1] << "\n";
|
||||
display(tout));
|
||||
rational a = get_coefficient(row_id1, x), b;
|
||||
row& r1 = m_rows[row_id1];
|
||||
ineq_type ty = r1.m_type;
|
||||
|
@ -1270,7 +1620,7 @@ namespace opt {
|
|||
case t_le:
|
||||
solve(row_id1, a, row_id2, x);
|
||||
break;
|
||||
case t_mod:
|
||||
case t_divides:
|
||||
// mod reduction already done.
|
||||
UNREACHABLE();
|
||||
break;
|
||||
|
@ -1284,6 +1634,7 @@ namespace opt {
|
|||
TRACE("opt1", tout << "updated eval " << x << " := " << eval(x) << "\n";);
|
||||
}
|
||||
retire_row(row_id1);
|
||||
TRACE("opt", display(tout << "solved v" << x << "\n"));
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
@ -30,7 +30,9 @@ namespace opt {
|
|||
t_eq,
|
||||
t_lt,
|
||||
t_le,
|
||||
t_mod
|
||||
t_divides,
|
||||
t_mod,
|
||||
t_div
|
||||
};
|
||||
|
||||
|
||||
|
@ -48,6 +50,14 @@ namespace opt {
|
|||
return x.m_id < y.m_id;
|
||||
}
|
||||
};
|
||||
|
||||
bool operator==(var const& other) const {
|
||||
return m_id == other.m_id && m_coeff == other.m_coeff;
|
||||
}
|
||||
|
||||
bool operator!=(var const& other) const {
|
||||
return !(*this == other);
|
||||
}
|
||||
};
|
||||
struct row {
|
||||
row(): m_type(t_le), m_value(0), m_alive(false) {}
|
||||
|
@ -57,6 +67,7 @@ namespace opt {
|
|||
ineq_type m_type; // inequality type
|
||||
rational m_value; // value of m_vars + m_coeff under interpretation of m_var2value.
|
||||
bool m_alive; // rows can be marked dead if they have been processed.
|
||||
unsigned m_id; // variable defined by row (used for mod_t and div_t)
|
||||
void reset() { m_vars.reset(); m_coeff.reset(); m_value.reset(); }
|
||||
|
||||
row& normalize();
|
||||
|
@ -87,7 +98,7 @@ namespace opt {
|
|||
vector<rational> m_var2value;
|
||||
bool_vector m_var2is_int;
|
||||
vector<var> m_new_vars;
|
||||
unsigned_vector m_lub, m_glb, m_mod;
|
||||
unsigned_vector m_lub, m_glb, m_divides, m_mod, m_div;
|
||||
unsigned_vector m_above, m_below;
|
||||
unsigned_vector m_retired_rows;
|
||||
|
||||
|
@ -114,7 +125,7 @@ namespace opt {
|
|||
|
||||
void mul_add(bool same_sign, unsigned row_id1, rational const& c, unsigned row_id2);
|
||||
|
||||
void mul_add(unsigned x, rational const& a1, unsigned row_src, rational const& a2, unsigned row_dst);
|
||||
void mul_add(unsigned x, rational a1, unsigned row_src, rational a2, unsigned row_dst);
|
||||
|
||||
void mul(unsigned dst, rational const& c);
|
||||
|
||||
|
@ -122,14 +133,18 @@ namespace opt {
|
|||
|
||||
void sub(unsigned dst, rational const& c);
|
||||
|
||||
void del_var(unsigned dst, unsigned x);
|
||||
|
||||
void set_row(unsigned row_id, vector<var> const& coeffs, rational const& c, rational const& m, ineq_type rel);
|
||||
|
||||
void add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type r);
|
||||
void add_lower_bound(unsigned x, rational const& lo);
|
||||
|
||||
void add_upper_bound(unsigned x, rational const& hi);
|
||||
|
||||
void add_constraint(vector<var> const& coeffs, rational const& c, rational const& m, ineq_type r, unsigned id);
|
||||
|
||||
void replace_var(unsigned row_id, unsigned x, rational const& A, unsigned y, rational const& B);
|
||||
|
||||
void replace_var(unsigned row_id, unsigned x, rational const& A, unsigned y, rational const& B, unsigned z);
|
||||
|
||||
void replace_var(unsigned row_id, unsigned x, rational const& C);
|
||||
|
||||
void normalize(unsigned row_id);
|
||||
|
@ -138,7 +153,7 @@ namespace opt {
|
|||
|
||||
unsigned new_row();
|
||||
|
||||
unsigned copy_row(unsigned row_id);
|
||||
unsigned copy_row(unsigned row_id, unsigned excl = UINT_MAX);
|
||||
|
||||
rational n_sign(rational const& b) const;
|
||||
|
||||
|
@ -150,7 +165,11 @@ namespace opt {
|
|||
|
||||
def solve_for(unsigned row_id, unsigned x, bool compute_def);
|
||||
|
||||
def solve_mod(unsigned x, unsigned_vector const& mod_rows, bool compute_def);
|
||||
def solve_divides(unsigned x, unsigned_vector const& divide_rows, bool compute_def);
|
||||
|
||||
def solve_mod(unsigned x, unsigned_vector const& divide_rows, bool compute_def);
|
||||
|
||||
def solve_div(unsigned x, unsigned_vector const& divide_rows, bool compute_def);
|
||||
|
||||
bool is_int(unsigned x) const { return m_var2is_int[x]; }
|
||||
|
||||
|
@ -173,6 +192,17 @@ namespace opt {
|
|||
// add a divisibility constraint. The row should divide m.
|
||||
void add_divides(vector<var> const& coeffs, rational const& c, rational const& m);
|
||||
|
||||
|
||||
// add sub-expression for modulus
|
||||
// v = add_mod(coeffs, m) means
|
||||
// v = coeffs mod m
|
||||
unsigned add_mod(vector<var> const& coeffs, rational const& c, rational const& m);
|
||||
|
||||
// add sub-expression for div
|
||||
// v = add_div(coeffs, m) means
|
||||
// v = coeffs div m
|
||||
unsigned add_div(vector<var> const& coeffs, rational const& c, rational const& m);
|
||||
|
||||
// Set the objective function (linear).
|
||||
void set_objective(vector<var> const& coeffs, rational const& c);
|
||||
|
||||
|
|
|
@ -23,7 +23,6 @@ Revision History:
|
|||
#include "ast/ast_util.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "ast/ast_pp.h"
|
||||
#include "ast/rewriter/th_rewriter.h"
|
||||
#include "ast/expr_functors.h"
|
||||
#include "ast/rewriter/expr_safe_replace.h"
|
||||
#include "math/simplex/model_based_opt.h"
|
||||
|
@ -37,8 +36,8 @@ namespace mbp {
|
|||
|
||||
ast_manager& m;
|
||||
arith_util a;
|
||||
bool m_check_purified { true }; // check that variables are properly pure
|
||||
bool m_apply_projection { false };
|
||||
bool m_check_purified = true; // check that variables are properly pure
|
||||
bool m_apply_projection = false;
|
||||
|
||||
|
||||
imp(ast_manager& m) :
|
||||
|
@ -100,8 +99,6 @@ namespace mbp {
|
|||
rational r1, r2;
|
||||
expr_ref val1 = eval(e1);
|
||||
expr_ref val2 = eval(e2);
|
||||
//TRACE("qe", tout << mk_pp(e1, m) << " " << val1 << "\n";);
|
||||
//TRACE("qe", tout << mk_pp(e2, m) << " " << val2 << "\n";);
|
||||
if (!a.is_numeral(val1, r1)) return false;
|
||||
if (!a.is_numeral(val2, r2)) return false;
|
||||
SASSERT(r1 != r2);
|
||||
|
@ -174,6 +171,16 @@ namespace mbp {
|
|||
expr* t1, * t2, * t3;
|
||||
rational mul1;
|
||||
expr_ref val(m);
|
||||
|
||||
auto add_def = [&](expr* t1, rational const& m, vars& coeffs) {
|
||||
obj_map<expr, rational> ts0;
|
||||
rational mul0(1), c0(0);
|
||||
linearize(mbo, eval, mul0, t1, c0, fmls, ts0, tids);
|
||||
extract_coefficients(mbo, eval, ts0, tids, coeffs);
|
||||
insert_mul(t, mul, ts);
|
||||
return c0;
|
||||
};
|
||||
|
||||
if (a.is_mul(t, t1, t2) && is_numeral(t1, mul1))
|
||||
linearize(mbo, eval, mul * mul1, t2, c, fmls, ts, tids);
|
||||
else if (a.is_mul(t, t1, t2) && is_numeral(t2, mul1))
|
||||
|
@ -210,11 +217,10 @@ namespace mbp {
|
|||
else if (a.is_mod(t, t1, t2) && is_numeral(t2, mul1) && !mul1.is_zero()) {
|
||||
rational r;
|
||||
val = eval(t);
|
||||
if (!a.is_numeral(val, r)) {
|
||||
if (!a.is_numeral(val, r))
|
||||
throw default_exception("mbp evaluation didn't produce an integer");
|
||||
}
|
||||
c += mul * r;
|
||||
// t1 mod mul1 == r
|
||||
|
||||
rational c0(-r), mul0(1);
|
||||
obj_map<expr, rational> ts0;
|
||||
linearize(mbo, eval, mul0, t1, c0, fmls, ts0, tids);
|
||||
|
@ -222,9 +228,20 @@ namespace mbp {
|
|||
extract_coefficients(mbo, eval, ts0, tids, coeffs);
|
||||
mbo.add_divides(coeffs, c0, mul1);
|
||||
}
|
||||
else {
|
||||
insert_mul(t, mul, ts);
|
||||
else if (false && a.is_mod(t, t1, t2) && is_numeral(t2, mul1) && mul1 > 0) {
|
||||
// v = t1 mod mul1
|
||||
vars coeffs;
|
||||
rational c0 = add_def(t1, mul1, coeffs);
|
||||
tids.insert(t, mbo.add_mod(coeffs, c0, mul1));
|
||||
}
|
||||
else if (false && a.is_idiv(t, t1, t2) && is_numeral(t2, mul1) && mul1 > 0) {
|
||||
// v = t1 div mul1
|
||||
vars coeffs;
|
||||
rational c0 = add_def(t1, mul1, coeffs);
|
||||
tids.insert(t, mbo.add_div(coeffs, c0, mul1));
|
||||
}
|
||||
else
|
||||
insert_mul(t, mul, ts);
|
||||
}
|
||||
|
||||
bool is_numeral(expr* t, rational& r) {
|
||||
|
@ -321,9 +338,19 @@ namespace mbp {
|
|||
}
|
||||
|
||||
// bail on variables in non-linear sub-terms
|
||||
auto is_pure = [&](expr* e) {
|
||||
expr* x, * y;
|
||||
rational r;
|
||||
if (a.is_mod(e, x, y) && a.is_numeral(y))
|
||||
return true;
|
||||
if (a.is_idiv(e, x, y) && a.is_numeral(y, r) && r > 0)
|
||||
return true;
|
||||
return false;
|
||||
};
|
||||
|
||||
for (auto& kv : tids) {
|
||||
expr* e = kv.m_key;
|
||||
if (is_arith(e) && !var_mark.is_marked(e))
|
||||
if (is_arith(e) && !is_pure(e) && !var_mark.is_marked(e))
|
||||
mark_rec(fmls_mark, e);
|
||||
}
|
||||
if (m_check_purified) {
|
||||
|
@ -331,7 +358,7 @@ namespace mbp {
|
|||
mark_rec(fmls_mark, fml);
|
||||
for (auto& kv : tids) {
|
||||
expr* e = kv.m_key;
|
||||
if (!var_mark.is_marked(e))
|
||||
if (!var_mark.is_marked(e) && !is_pure(e))
|
||||
mark_rec(fmls_mark, e);
|
||||
}
|
||||
}
|
||||
|
@ -399,16 +426,77 @@ namespace mbp {
|
|||
}
|
||||
}
|
||||
|
||||
void rows2fmls(vector<row> const& rows, ptr_vector<expr> const& index2expr, expr_ref_vector& fmls) {
|
||||
for (row const& r : rows) {
|
||||
expr_ref_vector ts(m);
|
||||
expr_ref t(m), s(m), val(m);
|
||||
if (r.m_vars.empty()) {
|
||||
continue;
|
||||
expr_ref id2expr(u_map<row> const& def_vars, ptr_vector<expr> const& index2expr, unsigned id) {
|
||||
row r;
|
||||
if (def_vars.find(id, r))
|
||||
return row2expr(def_vars, index2expr, r);
|
||||
return expr_ref(index2expr[id], m);
|
||||
}
|
||||
if (r.m_vars.size() == 1 && r.m_vars[0].m_coeff.is_neg() && r.m_type != opt::t_mod) {
|
||||
|
||||
expr_ref row2expr(u_map<row> const& def_vars, ptr_vector<expr> const& index2expr, row const& r) {
|
||||
expr_ref_vector ts(m);
|
||||
expr_ref t(m);
|
||||
rational n;
|
||||
for (var const& v : r.m_vars) {
|
||||
t = id2expr(def_vars, index2expr, v.m_id);
|
||||
if (a.is_numeral(t, n) && n == 0)
|
||||
continue;
|
||||
else if (a.is_numeral(t, n))
|
||||
t = a.mk_numeral(v.m_coeff * n, a.is_int(t));
|
||||
else if (!v.m_coeff.is_one())
|
||||
t = a.mk_mul(a.mk_numeral(v.m_coeff, a.is_int(t)), t);
|
||||
ts.push_back(t);
|
||||
}
|
||||
switch (r.m_type) {
|
||||
case opt::t_mod:
|
||||
if (ts.empty()) {
|
||||
t = a.mk_int(mod(r.m_coeff, r.m_mod));
|
||||
return t;
|
||||
}
|
||||
ts.push_back(a.mk_int(r.m_coeff));
|
||||
t = mk_add(ts);
|
||||
t = a.mk_mod(t, a.mk_int(r.m_mod));
|
||||
return t;
|
||||
case opt::t_div:
|
||||
if (ts.empty()) {
|
||||
t = a.mk_int(div(r.m_coeff, r.m_mod));
|
||||
return t;
|
||||
}
|
||||
ts.push_back(a.mk_int(r.m_coeff));
|
||||
t = mk_add(ts);
|
||||
t = a.mk_idiv(t, a.mk_int(r.m_mod));
|
||||
return t;
|
||||
case opt::t_divides:
|
||||
ts.push_back(a.mk_int(r.m_coeff));
|
||||
return mk_add(ts);
|
||||
default:
|
||||
return mk_add(ts);
|
||||
}
|
||||
}
|
||||
|
||||
void rows2fmls(vector<row> const& rows, ptr_vector<expr> const& index2expr, expr_ref_vector& fmls) {
|
||||
|
||||
u_map<row> def_vars;
|
||||
for (row const& r : rows) {
|
||||
if (r.m_type == opt::t_mod)
|
||||
def_vars.insert(r.m_id, r);
|
||||
else if (r.m_type == opt::t_div)
|
||||
def_vars.insert(r.m_id, r);
|
||||
}
|
||||
|
||||
for (row const& r : rows) {
|
||||
expr_ref t(m), s(m), val(m);
|
||||
|
||||
if (r.m_vars.empty())
|
||||
continue;
|
||||
if (r.m_type == opt::t_mod)
|
||||
continue;
|
||||
if (r.m_type == opt::t_div)
|
||||
continue;
|
||||
|
||||
if (r.m_vars.size() == 1 && r.m_vars[0].m_coeff.is_neg() && r.m_type != opt::t_divides) {
|
||||
var const& v = r.m_vars[0];
|
||||
t = index2expr[v.m_id];
|
||||
t = id2expr(def_vars, index2expr, v.m_id);
|
||||
if (!v.m_coeff.is_minus_one()) {
|
||||
t = a.mk_mul(a.mk_numeral(-v.m_coeff, a.is_int(t)), t);
|
||||
}
|
||||
|
@ -422,24 +510,14 @@ namespace mbp {
|
|||
fmls.push_back(t);
|
||||
continue;
|
||||
}
|
||||
for (var const& v : r.m_vars) {
|
||||
t = index2expr[v.m_id];
|
||||
if (!v.m_coeff.is_one()) {
|
||||
t = a.mk_mul(a.mk_numeral(v.m_coeff, a.is_int(t)), t);
|
||||
}
|
||||
ts.push_back(t);
|
||||
}
|
||||
t = mk_add(ts);
|
||||
t = row2expr(def_vars, index2expr, r);
|
||||
s = a.mk_numeral(-r.m_coeff, r.m_coeff.is_int() && a.is_int(t));
|
||||
switch (r.m_type) {
|
||||
case opt::t_lt: t = a.mk_lt(t, s); break;
|
||||
case opt::t_le: t = a.mk_le(t, s); break;
|
||||
case opt::t_eq: t = a.mk_eq(t, s); break;
|
||||
case opt::t_mod:
|
||||
if (!r.m_coeff.is_zero()) {
|
||||
t = a.mk_sub(t, s);
|
||||
}
|
||||
t = a.mk_eq(a.mk_mod(t, a.mk_numeral(r.m_mod, true)), a.mk_int(0));
|
||||
case opt::t_divides:
|
||||
t = a.mk_eq(a.mk_mod(t, a.mk_int(r.m_mod)), a.mk_int(0));
|
||||
break;
|
||||
}
|
||||
fmls.push_back(t);
|
||||
|
|
|
@ -241,9 +241,8 @@ namespace qe {
|
|||
while (sz0 != todo.size()) {
|
||||
app* a = to_app(todo.back());
|
||||
todo.pop_back();
|
||||
if (mark.is_marked(a)) {
|
||||
if (mark.is_marked(a))
|
||||
continue;
|
||||
}
|
||||
|
||||
mark.mark(a);
|
||||
if (m_lit2pred.find(a, p)) {
|
||||
|
@ -284,9 +283,8 @@ namespace qe {
|
|||
m_elevel.insert(r, l);
|
||||
eq = m.mk_eq(r, a);
|
||||
defs.push_back(eq);
|
||||
if (!is_predicate(a, l.max())) {
|
||||
if (!is_predicate(a, l.max()))
|
||||
insert(r, l);
|
||||
}
|
||||
level.merge(l);
|
||||
}
|
||||
}
|
||||
|
@ -637,57 +635,55 @@ namespace qe {
|
|||
check_cancel();
|
||||
expr_ref_vector asms(m_asms);
|
||||
m_pred_abs.get_assumptions(m_model.get(), asms);
|
||||
if (m_model.get()) {
|
||||
if (m_model.get())
|
||||
validate_assumptions(*m_model.get(), asms);
|
||||
}
|
||||
TRACE("qe", tout << asms << "\n";);
|
||||
solver& s = get_kernel(m_level).s();
|
||||
lbool res = s.check_sat(asms);
|
||||
switch (res) {
|
||||
case l_true:
|
||||
s.get_model(m_model);
|
||||
CTRACE("qe", !m_model, tout << "no model\n");
|
||||
if (!m_model)
|
||||
return l_undef;
|
||||
SASSERT(validate_defs("check_sat"));
|
||||
SASSERT(!m_model.get() || validate_assumptions(*m_model.get(), asms));
|
||||
SASSERT(validate_model(asms));
|
||||
TRACE("qe", s.display(tout); display(tout << "\n", *m_model.get()); display(tout, asms); );
|
||||
if (m_level == 0) {
|
||||
if (m_level == 0)
|
||||
m_model_save = m_model;
|
||||
}
|
||||
push();
|
||||
if (m_level == 1 && m_mode == qsat_maximize) {
|
||||
if (m_level == 1 && m_mode == qsat_maximize)
|
||||
maximize_model();
|
||||
}
|
||||
break;
|
||||
case l_false:
|
||||
switch (m_level) {
|
||||
case 0:
|
||||
return l_false;
|
||||
case 1:
|
||||
if (m_mode == qsat_sat) {
|
||||
if (m_mode == qsat_sat)
|
||||
return l_true;
|
||||
}
|
||||
|
||||
if (m_model.get()) {
|
||||
SASSERT(validate_assumptions(*m_model.get(), asms));
|
||||
if (!project_qe(asms)) return l_undef;
|
||||
if (!project_qe(asms))
|
||||
return l_undef;
|
||||
}
|
||||
else {
|
||||
else
|
||||
pop(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (m_model.get()) {
|
||||
if (!project(asms)) return l_undef;
|
||||
if (!project(asms))
|
||||
return l_undef;
|
||||
}
|
||||
else {
|
||||
else
|
||||
pop(1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case l_undef:
|
||||
TRACE("qe", tout << "check-sat is undef\n");
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
@ -833,11 +829,10 @@ namespace qe {
|
|||
}
|
||||
}
|
||||
|
||||
bool get_core(expr_ref_vector& core, unsigned level) {
|
||||
void get_core(expr_ref_vector& core, unsigned level) {
|
||||
SASSERT(validate_defs("get_core"));
|
||||
get_kernel(level).get_core(core);
|
||||
m_pred_abs.pred2lit(core);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool minimize_core(expr_ref_vector& core, unsigned level) {
|
||||
|
@ -905,9 +900,7 @@ namespace qe {
|
|||
SASSERT(m_level == 1);
|
||||
expr_ref fml(m);
|
||||
model& mdl = *m_model.get();
|
||||
if (!get_core(core, m_level)) {
|
||||
return false;
|
||||
}
|
||||
get_core(core, m_level);
|
||||
SASSERT(validate_core(mdl, core));
|
||||
get_vars(m_level);
|
||||
SASSERT(validate_assumptions(mdl, core));
|
||||
|
@ -927,7 +920,7 @@ namespace qe {
|
|||
}
|
||||
|
||||
bool project(expr_ref_vector& core) {
|
||||
if (!get_core(core, m_level)) return false;
|
||||
get_core(core, m_level);
|
||||
TRACE("qe", display(tout); display(tout << "core\n", core););
|
||||
SASSERT(m_level >= 2);
|
||||
expr_ref fml(m);
|
||||
|
@ -950,15 +943,18 @@ namespace qe {
|
|||
if (level.max() == UINT_MAX) {
|
||||
num_scopes = 2*(m_level/2);
|
||||
}
|
||||
else if (level.max() + 2 > m_level) {
|
||||
// fishy - this can happen.
|
||||
TRACE("qe", tout << "max-level: " << level.max() << " level: " << m_level << "\n");
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
if (level.max() + 2 > m_level) return false;
|
||||
SASSERT(level.max() + 2 <= m_level);
|
||||
num_scopes = m_level - level.max();
|
||||
SASSERT(num_scopes >= 2);
|
||||
if ((num_scopes % 2) != 0) {
|
||||
if ((num_scopes % 2) != 0)
|
||||
--num_scopes;
|
||||
}
|
||||
}
|
||||
|
||||
pop(num_scopes);
|
||||
TRACE("qe", tout << "backtrack: " << num_scopes << " new level: " << m_level << "\nproject:\n" << core << "\n|->\n" << fml << "\n";);
|
||||
|
|
79
src/sat/smt/xor_solver.cpp
Normal file
79
src/sat/smt/xor_solver.cpp
Normal file
|
@ -0,0 +1,79 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
xor_solver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
XOR solver.
|
||||
Interface outline.
|
||||
|
||||
--*/
|
||||
|
||||
|
||||
#include "sat/smt/xor_solver.h"
|
||||
#include "sat/sat_simplifier_params.hpp"
|
||||
#include "sat/sat_xor_finder.h"
|
||||
|
||||
namespace xr {
|
||||
|
||||
solver::solver(euf::solver& ctx):
|
||||
th_solver(ctx.get_manager(), symbol("xor-solver"), ctx.get_manager().get_family_id("xor-solver"))
|
||||
{}
|
||||
|
||||
euf::th_solver* solver::clone(euf::solver& ctx) {
|
||||
// and relevant copy internal state
|
||||
return alloc(solver, ctx);
|
||||
}
|
||||
|
||||
void solver::asserted(sat::literal l) {
|
||||
|
||||
}
|
||||
|
||||
bool solver::unit_propagate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
void solver::get_antecedents(sat::literal l, sat::ext_justification_idx idx,
|
||||
sat::literal_vector & r, bool probing) {
|
||||
|
||||
}
|
||||
|
||||
sat::check_result solver::check() {
|
||||
return sat::check_result::CR_DONE;
|
||||
}
|
||||
|
||||
void solver::push() {
|
||||
}
|
||||
|
||||
void solver::pop(unsigned n) {
|
||||
}
|
||||
|
||||
// inprocessing
|
||||
// pre_simplify: decompile all xor constraints to allow other in-processing.
|
||||
// simplify: recompile clauses to xor constraints
|
||||
// literals that get added to xor constraints are tagged with the theory.
|
||||
void solver::pre_simplify() {
|
||||
|
||||
}
|
||||
|
||||
void solver::simplify() {
|
||||
|
||||
}
|
||||
|
||||
std::ostream& solver::display(std::ostream& out) const {
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& solver::display_justification(std::ostream& out, sat::ext_justification_idx idx) const {
|
||||
return out;
|
||||
}
|
||||
|
||||
std::ostream& solver::display_constraint(std::ostream& out, sat::ext_constraint_idx idx) const {
|
||||
return out;
|
||||
}
|
||||
|
||||
}
|
||||
|
48
src/sat/smt/xor_solver.h
Normal file
48
src/sat/smt/xor_solver.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*++
|
||||
Copyright (c) 2014 Microsoft Corporation
|
||||
|
||||
Module Name:
|
||||
|
||||
xor_solver.h
|
||||
|
||||
Abstract:
|
||||
|
||||
XOR solver.
|
||||
Interface outline.
|
||||
|
||||
--*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "sat/smt/euf_solver.h"
|
||||
|
||||
namespace xr {
|
||||
class solver : public euf::th_solver {
|
||||
public:
|
||||
solver(euf::solver& ctx);
|
||||
|
||||
th_solver* clone(euf::solver& ctx) override;
|
||||
|
||||
sat::literal internalize(expr* e, bool sign, bool root, bool redundant) override { UNREACHABLE(); return sat::null_literal; }
|
||||
|
||||
void internalize(expr* e, bool redundant) override { UNREACHABLE(); }
|
||||
|
||||
|
||||
void asserted(sat::literal l) override;
|
||||
bool unit_propagate() override;
|
||||
void get_antecedents(sat::literal l, sat::ext_justification_idx idx, sat::literal_vector & r, bool probing) override;
|
||||
|
||||
void pre_simplify() override;
|
||||
void simplify() override;
|
||||
|
||||
sat::check_result check() override;
|
||||
void push() override;
|
||||
void pop(unsigned n) override;
|
||||
|
||||
std::ostream& display(std::ostream& out) const override;
|
||||
std::ostream& display_justification(std::ostream& out, sat::ext_justification_idx idx) const override;
|
||||
std::ostream& display_constraint(std::ostream& out, sat::ext_constraint_idx idx) const override;
|
||||
|
||||
};
|
||||
|
||||
}
|
|
@ -23,6 +23,7 @@ Revision History:
|
|||
#include "ast/rewriter/var_subst.h"
|
||||
#include "smt/smt_context.h"
|
||||
#include "smt/qi_queue.h"
|
||||
#include <iostream>
|
||||
|
||||
namespace smt {
|
||||
|
||||
|
@ -228,15 +229,12 @@ namespace smt {
|
|||
|
||||
|
||||
TRACE("qi_queue", tout << "new instance:\n" << mk_pp(instance, m) << "\n";);
|
||||
TRACE("qi_queue_instance", tout << "new instance:\n" << mk_pp(instance, m) << "\n";);
|
||||
expr_ref s_instance(m);
|
||||
proof_ref pr(m);
|
||||
m_context.get_rewriter()(instance, s_instance, pr);
|
||||
|
||||
TRACE("qi_queue_bug", tout << "new instance after simplification:\n" << s_instance << "\n";);
|
||||
if (m.is_true(s_instance)) {
|
||||
TRACE("checker", tout << "reduced to true, before:\n" << mk_ll_pp(instance, m););
|
||||
|
||||
STRACE("instance", tout << "Instance reduced to true\n";);
|
||||
stat -> inc_num_instances_simplify_true();
|
||||
if (m.has_trace_stream()) {
|
||||
|
@ -250,9 +248,11 @@ namespace smt {
|
|||
std::cout << "instantiate\n";
|
||||
enode_vector _bindings(num_bindings, bindings);
|
||||
for (auto * b : _bindings)
|
||||
std::cout << enode_pp(b, m_context) << " ";
|
||||
std::cout << mk_pp(b->get_expr(), m) << " ";
|
||||
std::cout << "\n";
|
||||
std::cout << mk_pp(q, m) << "\n";
|
||||
std::cout << "instance\n";
|
||||
std::cout << instance << "\n";
|
||||
#endif
|
||||
|
||||
TRACE("qi_queue", tout << "simplified instance:\n" << s_instance << "\n";);
|
||||
|
|
|
@ -243,6 +243,8 @@ namespace smt {
|
|||
func_decl * f = nullptr;
|
||||
if (autil.is_as_array(sk_value, f) && cex->get_func_interp(f) && cex->get_func_interp(f)->get_interp()) {
|
||||
expr_ref body(cex->get_func_interp(f)->get_interp(), m);
|
||||
if (contains_model_value(body))
|
||||
return false;
|
||||
ptr_vector<sort> sorts(f->get_arity(), f->get_domain());
|
||||
svector<symbol> names;
|
||||
for (unsigned i = 0; i < f->get_arity(); ++i) {
|
||||
|
|
|
@ -3507,16 +3507,15 @@ public:
|
|||
case lp::lp_status::OPTIMAL: {
|
||||
init_variable_values();
|
||||
TRACE("arith", display(tout << st << " v" << v << " vi: " << vi << "\n"););
|
||||
inf_rational val = get_value(v);
|
||||
// inf_rational val(term_max.x, term_max.y);
|
||||
auto val = value(v);
|
||||
blocker = mk_gt(v);
|
||||
return inf_eps(rational::zero(), val);
|
||||
return val;
|
||||
}
|
||||
case lp::lp_status::FEASIBLE: {
|
||||
inf_rational val = get_value(v);
|
||||
auto val = value(v);
|
||||
TRACE("arith", display(tout << st << " v" << v << " vi: " << vi << "\n"););
|
||||
blocker = mk_gt(v);
|
||||
return inf_eps(rational::zero(), val);
|
||||
return val;
|
||||
}
|
||||
default:
|
||||
SASSERT(st == lp::lp_status::UNBOUNDED);
|
||||
|
@ -3533,24 +3532,20 @@ public:
|
|||
rational r = val.x;
|
||||
expr_ref e(m);
|
||||
if (a.is_int(obj->get_sort())) {
|
||||
if (r.is_int()) {
|
||||
if (r.is_int())
|
||||
r += rational::one();
|
||||
}
|
||||
else {
|
||||
else
|
||||
r = ceil(r);
|
||||
}
|
||||
e = a.mk_numeral(r, obj->get_sort());
|
||||
e = a.mk_ge(obj, e);
|
||||
}
|
||||
else {
|
||||
e = a.mk_numeral(r, obj->get_sort());
|
||||
if (val.y.is_neg()) {
|
||||
if (val.y.is_neg())
|
||||
e = a.mk_ge(obj, e);
|
||||
}
|
||||
else {
|
||||
else
|
||||
e = a.mk_gt(obj, e);
|
||||
}
|
||||
}
|
||||
TRACE("opt", tout << "v" << v << " " << val << " " << r << " " << e << "\n";);
|
||||
return e;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue