mirror of
https://github.com/Z3Prover/z3
synced 2025-04-08 10:25:18 +00:00
adding pre-processing to nlsat for equations
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
5bc4c9809e
commit
79a9dfd8fd
|
@ -370,7 +370,7 @@ public:
|
|||
app * mk_lt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_LT, arg1, arg2); }
|
||||
app * mk_gt(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_GT, arg1, arg2); }
|
||||
|
||||
app * mk_add(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
|
||||
app * mk_add(unsigned num_args, expr * const * args) const { return num_args == 1 && is_app(args[0]) ? to_app(args[0]) : m_manager.mk_app(m_afid, OP_ADD, num_args, args); }
|
||||
app * mk_add(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2); }
|
||||
app * mk_add(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_ADD, arg1, arg2, arg3); }
|
||||
|
||||
|
@ -378,7 +378,7 @@ public:
|
|||
app * mk_sub(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_SUB, num_args, args); }
|
||||
app * mk_mul(expr * arg1, expr * arg2) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2); }
|
||||
app * mk_mul(expr * arg1, expr * arg2, expr* arg3) const { return m_manager.mk_app(m_afid, OP_MUL, arg1, arg2, arg3); }
|
||||
app * mk_mul(unsigned num_args, expr * const * args) const { return m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
|
||||
app * mk_mul(unsigned num_args, expr * const * args) const { return num_args == 1 && is_app(args[0]) ? to_app(args[0]) : m_manager.mk_app(m_afid, OP_MUL, num_args, args); }
|
||||
app * mk_uminus(expr * arg) const { return m_manager.mk_app(m_afid, OP_UMINUS, arg); }
|
||||
app * mk_div(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_DIV, arg1, arg2); }
|
||||
app * mk_idiv(expr * arg1, expr * arg2) { return m_manager.mk_app(m_afid, OP_IDIV, arg1, arg2); }
|
||||
|
|
|
@ -150,7 +150,6 @@ namespace polynomial {
|
|||
return r;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
\brief Monomials (power products)
|
||||
*/
|
||||
|
@ -192,7 +191,7 @@ namespace polynomial {
|
|||
};
|
||||
|
||||
static unsigned get_obj_size(unsigned sz) { return sizeof(monomial) + sz * sizeof(power); }
|
||||
|
||||
|
||||
monomial(unsigned id, unsigned sz, power const * pws, unsigned h):
|
||||
m_ref_count(0),
|
||||
m_id(id),
|
||||
|
@ -257,9 +256,7 @@ namespace polynomial {
|
|||
if (m_size < SMALL_MONOMIAL) {
|
||||
// use linear search for small monomials
|
||||
// search backwards since we usually ask for the degree of "big" variables
|
||||
unsigned i = last;
|
||||
while (i > 0) {
|
||||
--i;
|
||||
for (unsigned i = last; i-- > 0; ) {
|
||||
if (get_var(i) == x)
|
||||
return i;
|
||||
}
|
||||
|
@ -798,9 +795,8 @@ namespace polynomial {
|
|||
dec_ref(m_unit);
|
||||
CTRACE("polynomial", !m_monomials.empty(),
|
||||
tout << "monomials leaked\n";
|
||||
monomial_table::iterator it = m_monomials.begin(); monomial_table::iterator end = m_monomials.end();
|
||||
for (; it != end; ++it) {
|
||||
(*it)->display(tout); tout << "\n";
|
||||
for (auto * m : m_monomials) {
|
||||
m->display(tout); tout << "\n";
|
||||
});
|
||||
SASSERT(m_monomials.empty());
|
||||
if (m_own_allocator)
|
||||
|
@ -1510,6 +1506,8 @@ namespace polynomial {
|
|||
unsigned id() const { return m_id; }
|
||||
unsigned size() const { return m_size; }
|
||||
monomial * m(unsigned idx) const { SASSERT(idx < size()); return m_ms[idx]; }
|
||||
monomial *const* begin() const { return m_ms; }
|
||||
monomial *const* end() const { return m_ms + size(); }
|
||||
numeral const & a(unsigned idx) const { SASSERT(idx < size()); return m_as[idx]; }
|
||||
numeral & a(unsigned idx) { SASSERT(idx < size()); return m_as[idx]; }
|
||||
numeral const * as() const { return m_as; }
|
||||
|
@ -1773,11 +1771,9 @@ namespace polynomial {
|
|||
}
|
||||
|
||||
bool manager::is_linear(polynomial const * p) {
|
||||
unsigned sz = p->size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
if (!is_linear(p->m(0)))
|
||||
for (monomial* m : *p)
|
||||
if (!is_linear(m))
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -2396,6 +2392,7 @@ namespace polynomial {
|
|||
return mm().is_valid(x);
|
||||
}
|
||||
|
||||
|
||||
void add_del_eh(del_eh * eh) {
|
||||
eh->m_next = m_del_eh;
|
||||
m_del_eh = eh;
|
||||
|
@ -6101,6 +6098,33 @@ namespace polynomial {
|
|||
});
|
||||
}
|
||||
|
||||
lbool sign(monomial* m, numeral const& c, svector<lbool> const& sign_of_vars) {
|
||||
unsigned sz = size(m);
|
||||
lbool sign1 = m_manager.is_pos(c) ? l_true : l_false;
|
||||
for (unsigned i = 0; i < sz; ++i) {
|
||||
var v = get_var(m, i);
|
||||
unsigned d = degree(m, i);
|
||||
lbool sign2 = sign_of_vars.get(v, l_undef);
|
||||
if (sign2 == l_undef)
|
||||
return l_undef;
|
||||
else if (1 == (d % 2) && sign2 == l_false) {
|
||||
sign1 = sign1 == l_true ? l_false : l_true;
|
||||
}
|
||||
}
|
||||
return sign1;
|
||||
}
|
||||
|
||||
lbool sign(polynomial const * p, svector<lbool> const& sign_of_vars) {
|
||||
unsigned sz = size(p);
|
||||
if (sz == 0) return l_undef;
|
||||
lbool sign1 = sign(p->m(0), p->a(0), sign_of_vars);
|
||||
for (unsigned i = 1; sign1 != l_undef && i < sz; ++i) {
|
||||
if (sign(p->m(i), p->a(i), sign_of_vars) != sign1)
|
||||
return l_undef;
|
||||
}
|
||||
return sign1;
|
||||
}
|
||||
|
||||
bool is_pos(polynomial const * p) {
|
||||
bool found_unit = false;
|
||||
unsigned sz = p->size();
|
||||
|
@ -6372,6 +6396,31 @@ namespace polynomial {
|
|||
R.add(new_a, mk_monomial(new_m));
|
||||
}
|
||||
return R.mk();
|
||||
}
|
||||
|
||||
void substitute(polynomial const* r, var x, polynomial const* p, polynomial const* q, polynomial_ref& result) {
|
||||
unsigned md = degree(r, x);
|
||||
if (md == 0) {
|
||||
result = const_cast<polynomial*>(r);
|
||||
return;
|
||||
}
|
||||
result = 0;
|
||||
polynomial_ref p1(pm()), q1(pm());
|
||||
polynomial_ref_buffer ps(pm());
|
||||
unsigned sz = r->size();
|
||||
for (unsigned i = 0; i < sz; i++) {
|
||||
monomial * m0 = r->m(i);
|
||||
unsigned dm = m0->degree_of(x);
|
||||
SASSERT(md >= dm);
|
||||
monomial_ref m1(div_x(m0, x), pm());
|
||||
pw(p, dm, p1);
|
||||
pw(q, md - dm, q1);
|
||||
p1 = mul(r->a(i), m1, p1 * q1);
|
||||
if (result)
|
||||
result = add(result, p1);
|
||||
else
|
||||
result = p1;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -6918,6 +6967,18 @@ namespace polynomial {
|
|||
return m_imp->m().set_zp(p);
|
||||
}
|
||||
|
||||
bool manager::is_var(polynomial const* p, var& v) {
|
||||
return p->size() == 1 && is_var(p->m(0), v) && m_imp->m().is_one(p->a(0));
|
||||
}
|
||||
|
||||
bool manager::is_var(monomial const* m, var& v) {
|
||||
return m->size() == 1 && m->degree(0) == 1 && (v = m->get_var(0), true);
|
||||
}
|
||||
|
||||
bool manager::is_var_num(polynomial const* p, var& v, scoped_numeral& n) {
|
||||
return p->size() == 2 && m_imp->m().is_one(p->a(0)) && is_var(p->m(0), v) && is_unit(p->m(1)) && (n = p->a(1), true);
|
||||
}
|
||||
|
||||
small_object_allocator & manager::allocator() const {
|
||||
return m_imp->mm().allocator();
|
||||
}
|
||||
|
@ -7271,6 +7332,10 @@ namespace polynomial {
|
|||
void manager::psc_chain(polynomial const * p, polynomial const * q, var x, polynomial_ref_vector & S) {
|
||||
m_imp->psc_chain(p, q, x, S);
|
||||
}
|
||||
|
||||
lbool manager::sign(polynomial const * p, svector<lbool> const& sign_of_vars) {
|
||||
return m_imp->sign(p, sign_of_vars);
|
||||
}
|
||||
|
||||
bool manager::is_pos(polynomial const * p) {
|
||||
return m_imp->is_pos(p);
|
||||
|
@ -7307,6 +7372,10 @@ namespace polynomial {
|
|||
polynomial * manager::substitute(polynomial const * p, unsigned xs_sz, var const * xs, numeral const * vs) {
|
||||
return m_imp->substitute(p, xs_sz, xs, vs);
|
||||
}
|
||||
|
||||
void manager::substitute(polynomial const* r, var x, polynomial const* p, polynomial const* q, polynomial_ref& result) {
|
||||
m_imp->substitute(r, x, p, q, result);
|
||||
}
|
||||
|
||||
void manager::factor(polynomial const * p, factors & r, factor_params const & params) {
|
||||
m_imp->factor(p, r, params);
|
||||
|
|
|
@ -29,6 +29,7 @@ Notes:
|
|||
#include "util/params.h"
|
||||
#include "util/mpbqi.h"
|
||||
#include "util/rlimit.h"
|
||||
#include "util/lbool.h"
|
||||
|
||||
class small_object_allocator;
|
||||
|
||||
|
@ -98,7 +99,7 @@ namespace polynomial {
|
|||
};
|
||||
|
||||
struct display_var_proc {
|
||||
virtual void operator()(std::ostream & out, var x) const { out << "x" << x; }
|
||||
virtual std::ostream& operator()(std::ostream & out, var x) const { return out << "x" << x; }
|
||||
};
|
||||
|
||||
class polynomial;
|
||||
|
@ -306,12 +307,27 @@ namespace polynomial {
|
|||
\brief Return true if m is linear (i.e., it is of the form 1 or x).
|
||||
*/
|
||||
static bool is_linear(monomial const * m);
|
||||
|
||||
|
||||
/**
|
||||
\brief Return true if all monomials in p are linear.
|
||||
*/
|
||||
static bool is_linear(polynomial const * p);
|
||||
|
||||
/**
|
||||
\brief Return true if the monomial is a variable.
|
||||
*/
|
||||
static bool is_var(monomial const* p, var& v);
|
||||
|
||||
/**
|
||||
\brief Return true if the polynomial is a variable.
|
||||
*/
|
||||
bool is_var(polynomial const* p, var& v);
|
||||
|
||||
/**
|
||||
\brief Return true if the polynomial is of the form x + k
|
||||
*/
|
||||
bool is_var_num(polynomial const* p, var& v, scoped_numeral& n);
|
||||
|
||||
/**
|
||||
\brief Return the degree of variable x in p.
|
||||
*/
|
||||
|
@ -860,7 +876,13 @@ namespace polynomial {
|
|||
\brief Return true if p is a square, and store its square root in r.
|
||||
*/
|
||||
bool sqrt(polynomial const * p, polynomial_ref & r);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
\brief obtain the sign of the polynomial given sign of variables.
|
||||
*/
|
||||
lbool sign(polynomial const* p, svector<lbool> const& sign_of_vars);
|
||||
|
||||
/**
|
||||
\brief Return true if p is always positive for any assignment of its variables.
|
||||
|
||||
|
@ -936,6 +958,13 @@ namespace polynomial {
|
|||
return substitute(p, 1, &x, &v);
|
||||
}
|
||||
|
||||
/**
|
||||
\brief Apply substiution [x -> p/q] in r.
|
||||
That is, given r \in Z[x, y_1, .., y_m] return
|
||||
polynomial q^k * r(p/q, y_1, .., y_m), where k is the maximal degree of x in r.
|
||||
*/
|
||||
void substitute(polynomial const* r, var x, polynomial const* p, polynomial const* q, polynomial_ref& result);
|
||||
|
||||
/**
|
||||
\brief Factorize the given polynomial p and store its factors in r.
|
||||
*/
|
||||
|
|
|
@ -44,6 +44,8 @@ namespace nlsat {
|
|||
bool is_learned() const { return m_learned; }
|
||||
literal * begin() { return m_lits; }
|
||||
literal * end() { return m_lits + m_size; }
|
||||
literal const * begin() const { return m_lits; }
|
||||
literal const * end() const { return m_lits + m_size; }
|
||||
literal const * c_ptr() const { return m_lits; }
|
||||
void inc_activity() { m_activity++; }
|
||||
void set_activity(unsigned v) { m_activity = v; }
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -35,7 +35,7 @@ namespace nlsat {
|
|||
struct imp;
|
||||
imp * m_imp;
|
||||
public:
|
||||
solver(reslimit& rlim, params_ref const & p);
|
||||
solver(reslimit& rlim, params_ref const & p, bool incremental);
|
||||
~solver();
|
||||
|
||||
/**
|
||||
|
|
|
@ -47,6 +47,8 @@ namespace nlsat {
|
|||
typedef polynomial::var_vector var_vector;
|
||||
typedef polynomial::manager pmanager;
|
||||
typedef polynomial::polynomial poly;
|
||||
typedef polynomial::monomial monomial;
|
||||
typedef polynomial::numeral numeral;
|
||||
const var null_var = polynomial::null_var;
|
||||
|
||||
const var true_bool_var = 0;
|
||||
|
|
|
@ -32,11 +32,11 @@ class nlsat_tactic : public tactic {
|
|||
ast_manager & m;
|
||||
expr_ref_vector m_var2expr;
|
||||
expr_display_var_proc(ast_manager & _m):m(_m), m_var2expr(_m) {}
|
||||
virtual void operator()(std::ostream & out, nlsat::var x) const {
|
||||
virtual std::ostream& operator()(std::ostream & out, nlsat::var x) const {
|
||||
if (x < m_var2expr.size())
|
||||
out << mk_ismt2_pp(m_var2expr.get(x), m);
|
||||
return out << mk_ismt2_pp(m_var2expr.get(x), m);
|
||||
else
|
||||
out << "x!" << x;
|
||||
return out << "x!" << x;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -51,7 +51,7 @@ class nlsat_tactic : public tactic {
|
|||
m(_m),
|
||||
m_params(p),
|
||||
m_display_var(_m),
|
||||
m_solver(m.limit(), p) {
|
||||
m_solver(m.limit(), p, false) {
|
||||
}
|
||||
|
||||
void updt_params(params_ref const & p) {
|
||||
|
|
|
@ -48,11 +48,15 @@ tactic * mk_qfnra_nlsat_tactic(ast_manager & m, params_ref const & p) {
|
|||
purify_p),
|
||||
mk_propagate_values_tactic(m, p),
|
||||
mk_solve_eqs_tactic(m, p),
|
||||
using_params(mk_purify_arith_tactic(m, p),
|
||||
purify_p),
|
||||
mk_elim_uncnstr_tactic(m, p),
|
||||
mk_elim_term_ite_tactic(m, p)),
|
||||
and_then(/* mk_degree_shift_tactic(m, p), */ // may affect full dimensionality detection
|
||||
factor,
|
||||
mk_solve_eqs_tactic(m, p),
|
||||
using_params(mk_purify_arith_tactic(m, p),
|
||||
purify_p),
|
||||
using_params(mk_simplify_tactic(m, p),
|
||||
main_p),
|
||||
mk_tseitin_cnf_core_tactic(m, p),
|
||||
|
|
|
@ -782,7 +782,7 @@ namespace qe {
|
|||
m(m),
|
||||
m_mode(mode),
|
||||
m_params(p),
|
||||
m_solver(m.limit(), p),
|
||||
m_solver(m.limit(), p, true),
|
||||
m_nftactic(0),
|
||||
m_rmodel(m_solver.am()),
|
||||
m_rmodel0(m_solver.am()),
|
||||
|
|
|
@ -44,6 +44,7 @@ class solve_eqs_tactic : public tactic {
|
|||
expr_sparse_mark m_candidate_set;
|
||||
ptr_vector<expr> m_candidates;
|
||||
ptr_vector<app> m_vars;
|
||||
expr_sparse_mark m_nonzero;
|
||||
ptr_vector<app> m_ordered_vars;
|
||||
bool m_produce_proofs;
|
||||
bool m_produce_unsat_cores;
|
||||
|
@ -55,8 +56,7 @@ class solve_eqs_tactic : public tactic {
|
|||
m_r_owner(r == 0 || owner),
|
||||
m_a_util(m),
|
||||
m_num_steps(0),
|
||||
m_num_eliminated_vars(0)
|
||||
{
|
||||
m_num_eliminated_vars(0) {
|
||||
updt_params(p);
|
||||
if (m_r == 0)
|
||||
m_r = mk_default_expr_replacer(m);
|
||||
|
@ -78,7 +78,7 @@ class solve_eqs_tactic : public tactic {
|
|||
void checkpoint() {
|
||||
if (m().canceled())
|
||||
throw tactic_exception(m().limit().get_cancel_msg());
|
||||
cooperate("solve-eqs");
|
||||
cooperate("solve-eqs");
|
||||
}
|
||||
|
||||
// Check if the number of occurrences of t is below the specified threshold :solve-eqs-max-occs
|
||||
|
@ -106,7 +106,8 @@ class solve_eqs_tactic : public tactic {
|
|||
}
|
||||
}
|
||||
bool trivial_solve(expr * lhs, expr * rhs, app_ref & var, expr_ref & def, proof_ref & pr) {
|
||||
if (trivial_solve1(lhs, rhs, var, def, pr)) return true;
|
||||
if (trivial_solve1(lhs, rhs, var, def, pr))
|
||||
return true;
|
||||
if (trivial_solve1(rhs, lhs, var, def, pr)) {
|
||||
if (m_produce_proofs) {
|
||||
pr = m().mk_commutativity(m().mk_eq(lhs, rhs));
|
||||
|
@ -187,6 +188,77 @@ class solve_eqs_tactic : public tactic {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void add_pos(expr* f) {
|
||||
expr* lhs = nullptr, *rhs = nullptr;
|
||||
rational val;
|
||||
if (m_a_util.is_le(f, lhs, rhs) && m_a_util.is_numeral(rhs, val) && val.is_neg()) {
|
||||
m_nonzero.mark(lhs);
|
||||
}
|
||||
else if (m_a_util.is_ge(f, lhs, rhs) && m_a_util.is_numeral(rhs, val) && val.is_pos()) {
|
||||
m_nonzero.mark(lhs);
|
||||
}
|
||||
else if (m().is_not(f, f)) {
|
||||
if (m_a_util.is_le(f, lhs, rhs) && m_a_util.is_numeral(rhs, val) && !val.is_neg()) {
|
||||
m_nonzero.mark(lhs);
|
||||
}
|
||||
else if (m_a_util.is_ge(f, lhs, rhs) && m_a_util.is_numeral(rhs, val) && !val.is_pos()) {
|
||||
m_nonzero.mark(lhs);
|
||||
}
|
||||
else if (m().is_eq(f, lhs, rhs) && m_a_util.is_numeral(rhs, val) && val.is_zero()) {
|
||||
m_nonzero.mark(lhs);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool is_nonzero(expr* e) {
|
||||
return m_nonzero.is_marked(e);
|
||||
}
|
||||
|
||||
bool isolate_var(app* arg, app_ref& var, expr_ref& div, unsigned i, app* lhs, expr* rhs) {
|
||||
if (!m_a_util.is_mul(arg)) return false;
|
||||
unsigned n = arg->get_num_args();
|
||||
for (unsigned j = 0; j < n; ++j) {
|
||||
expr* e = arg->get_arg(j);
|
||||
bool ok = is_uninterp_const(e) && check_occs(e) && !occurs(e, rhs) && !occurs_except(e, lhs, i);
|
||||
if (!ok) continue;
|
||||
var = to_app(e);
|
||||
for (unsigned k = 0; ok && k < n; ++k) {
|
||||
expr* arg_k = arg->get_arg(k);
|
||||
ok = k == j || (!occurs(var, arg_k) && is_nonzero(arg_k));
|
||||
}
|
||||
if (!ok) continue;
|
||||
ptr_vector<expr> args;
|
||||
for (unsigned k = 0; k < n; ++k) {
|
||||
if (k != j) args.push_back(arg->get_arg(k));
|
||||
}
|
||||
div = m_a_util.mk_mul(args.size(), args.c_ptr());
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool solve_nl(app * lhs, expr * rhs, expr* eq, app_ref& var, expr_ref & def, proof_ref & pr) {
|
||||
SASSERT(m_a_util.is_add(lhs));
|
||||
if (m_a_util.is_int(lhs)) return false;
|
||||
unsigned num = lhs->get_num_args();
|
||||
expr_ref div(m());
|
||||
for (unsigned i = 0; i < num; i++) {
|
||||
expr * arg = lhs->get_arg(i);
|
||||
if (is_app(arg) && isolate_var(to_app(arg), var, div, i, lhs, rhs)) {
|
||||
ptr_vector<expr> args;
|
||||
for (unsigned k = 0; k < num; ++k) {
|
||||
if (k != i) args.push_back(lhs->get_arg(k));
|
||||
}
|
||||
def = m_a_util.mk_sub(rhs, m_a_util.mk_add(args.size(), args.c_ptr()));
|
||||
def = m_a_util.mk_div(def, div);
|
||||
if (m_produce_proofs)
|
||||
pr = m().mk_rewrite(eq, m().mk_eq(var, def));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool solve_arith_core(app * lhs, expr * rhs, expr * eq, app_ref & var, expr_ref & def, proof_ref & pr) {
|
||||
SASSERT(m_a_util.is_add(lhs));
|
||||
|
@ -204,7 +276,8 @@ class solve_eqs_tactic : public tactic {
|
|||
break;
|
||||
}
|
||||
else if (m_a_util.is_mul(arg, a, v) &&
|
||||
is_uninterp_const(v) && !m_candidate_vars.is_marked(v) &&
|
||||
is_uninterp_const(v) &&
|
||||
!m_candidate_vars.is_marked(v) &&
|
||||
m_a_util.is_numeral(a, a_val) &&
|
||||
!a_val.is_zero() &&
|
||||
(!is_int || a_val.is_minus_one()) &&
|
||||
|
@ -252,16 +325,20 @@ class solve_eqs_tactic : public tactic {
|
|||
return
|
||||
(m_a_util.is_add(lhs) && solve_arith_core(to_app(lhs), rhs, eq, var, def, pr)) ||
|
||||
(m_a_util.is_add(rhs) && solve_arith_core(to_app(rhs), lhs, eq, var, def, pr));
|
||||
#if 0
|
||||
// better done inside of nlsat
|
||||
(m_a_util.is_add(lhs) && solve_nl(to_app(lhs), rhs, eq, var, def, pr)) ||
|
||||
(m_a_util.is_add(rhs) && solve_nl(to_app(rhs), lhs, eq, var, def, pr));
|
||||
#endif
|
||||
}
|
||||
|
||||
bool solve(expr * f, app_ref & var, expr_ref & def, proof_ref & pr) {
|
||||
if (m().is_eq(f)) {
|
||||
if (trivial_solve(to_app(f)->get_arg(0), to_app(f)->get_arg(1), var, def, pr))
|
||||
expr* arg1 = 0, *arg2 = 0;
|
||||
if (m().is_eq(f, arg1, arg2)) {
|
||||
if (trivial_solve(arg1, arg2, var, def, pr))
|
||||
return true;
|
||||
if (m_theory_solver) {
|
||||
expr * lhs = to_app(f)->get_arg(0);
|
||||
expr * rhs = to_app(f)->get_arg(1);
|
||||
if (solve_arith(lhs, rhs, f, var, def, pr))
|
||||
if (solve_arith(arg1, arg2, f, var, def, pr))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
@ -321,11 +398,14 @@ class solve_eqs_tactic : public tactic {
|
|||
m_candidate_set.reset();
|
||||
m_candidates.reset();
|
||||
m_vars.reset();
|
||||
|
||||
m_nonzero.reset();
|
||||
app_ref var(m());
|
||||
expr_ref def(m());
|
||||
proof_ref pr(m());
|
||||
unsigned size = g.size();
|
||||
for (unsigned idx = 0; idx < size; idx++) {
|
||||
add_pos(g.form(idx));
|
||||
}
|
||||
for (unsigned idx = 0; idx < size; idx++) {
|
||||
checkpoint();
|
||||
expr * f = g.form(idx);
|
||||
|
@ -347,10 +427,8 @@ class solve_eqs_tactic : public tactic {
|
|||
|
||||
TRACE("solve_eqs",
|
||||
tout << "candidate vars:\n";
|
||||
ptr_vector<app>::iterator it = m_vars.begin();
|
||||
ptr_vector<app>::iterator end = m_vars.end();
|
||||
for (; it != end; ++it) {
|
||||
tout << mk_ismt2_pp(*it, m()) << " ";
|
||||
for (app* v : m_vars) {
|
||||
tout << mk_ismt2_pp(v, m()) << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
}
|
||||
|
@ -374,12 +452,9 @@ class solve_eqs_tactic : public tactic {
|
|||
|
||||
typedef std::pair<expr *, unsigned> frame;
|
||||
svector<frame> todo;
|
||||
ptr_vector<app>::const_iterator it = m_vars.begin();
|
||||
ptr_vector<app>::const_iterator end = m_vars.end();
|
||||
unsigned num;
|
||||
for (; it != end; ++it) {
|
||||
unsigned num = 0;
|
||||
for (app* v : m_vars) {
|
||||
checkpoint();
|
||||
app * v = *it;
|
||||
if (!m_candidate_vars.is_marked(v))
|
||||
continue;
|
||||
todo.push_back(frame(v, 0));
|
||||
|
@ -483,20 +558,19 @@ class solve_eqs_tactic : public tactic {
|
|||
}
|
||||
|
||||
// cleanup
|
||||
it = m_vars.begin();
|
||||
for (unsigned idx = 0; it != end; ++it, ++idx) {
|
||||
if (!m_candidate_vars.is_marked(*it)) {
|
||||
unsigned idx = 0;
|
||||
for (expr* v : m_vars) {
|
||||
if (!m_candidate_vars.is_marked(v)) {
|
||||
m_candidate_set.mark(m_candidates[idx], false);
|
||||
}
|
||||
++idx;
|
||||
}
|
||||
|
||||
TRACE("solve_eqs",
|
||||
tout << "ordered vars:\n";
|
||||
ptr_vector<app>::iterator it = m_ordered_vars.begin();
|
||||
ptr_vector<app>::iterator end = m_ordered_vars.end();
|
||||
for (; it != end; ++it) {
|
||||
SASSERT(m_candidate_vars.is_marked(*it));
|
||||
tout << mk_ismt2_pp(*it, m()) << " ";
|
||||
for (app* v : m_ordered_vars) {
|
||||
SASSERT(m_candidate_vars.is_marked(v));
|
||||
tout << mk_ismt2_pp(v, m()) << " ";
|
||||
}
|
||||
tout << "\n";);
|
||||
m_candidate_vars.reset();
|
||||
|
@ -609,10 +683,7 @@ class solve_eqs_tactic : public tactic {
|
|||
if (m_produce_models) {
|
||||
if (mc.get() == 0)
|
||||
mc = alloc(gmc, m());
|
||||
ptr_vector<app>::iterator it = m_ordered_vars.begin();
|
||||
ptr_vector<app>::iterator end = m_ordered_vars.end();
|
||||
for (; it != end; ++it) {
|
||||
app * v = *it;
|
||||
for (app* v : m_ordered_vars) {
|
||||
expr * def = 0;
|
||||
proof * pr;
|
||||
expr_dependency * dep;
|
||||
|
|
Loading…
Reference in a new issue