mirror of
https://github.com/Z3Prover/z3
synced 2025-10-07 08:21:56 +00:00
merge
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
commit
3ce82ea8ce
35 changed files with 2434 additions and 1483 deletions
|
@ -36,7 +36,7 @@ def_module_params(module_name='smt',
|
|||
('bv.reflect', BOOL, True, 'create enode for every bit-vector term'),
|
||||
('bv.enable_int2bv', BOOL, True, 'enable support for int2bv and bv2int operators'),
|
||||
('arith.random_initial_value', BOOL, False, 'use random initial values in the simplex-based procedure for linear arithmetic'),
|
||||
('arith.solver', UINT, 2, 'arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination'),
|
||||
('arith.solver', UINT, 2, 'arithmetic solver: 0 - no solver, 1 - bellman-ford based solver (diff. logic only), 2 - simplex based solver, 3 - floyd-warshall based solver (diff. logic only) and no theory combination 4 - utvpi, 5 - infinitary lra, 6 - lra solver'),
|
||||
('arith.nl', BOOL, True, '(incomplete) nonlinear arithmetic support based on Groebner basis and interval propagation'),
|
||||
('arith.nl.gb', BOOL, True, 'groebner Basis computation, this option is ignored when arith.nl=false'),
|
||||
('arith.nl.branching', BOOL, True, 'branching on integer variables in non linear clusters'),
|
||||
|
|
|
@ -23,12 +23,13 @@ Revision History:
|
|||
#include"params.h"
|
||||
|
||||
enum arith_solver_id {
|
||||
AS_NO_ARITH,
|
||||
AS_DIFF_LOGIC,
|
||||
AS_ARITH,
|
||||
AS_DENSE_DIFF_LOGIC,
|
||||
AS_UTVPI,
|
||||
AS_OPTINF
|
||||
AS_NO_ARITH, // 0
|
||||
AS_DIFF_LOGIC, // 1
|
||||
AS_ARITH, // 2
|
||||
AS_DENSE_DIFF_LOGIC, // 3
|
||||
AS_UTVPI, // 4
|
||||
AS_OPTINF, // 5
|
||||
AS_LRA // 6
|
||||
};
|
||||
|
||||
enum bound_prop_mode {
|
||||
|
|
|
@ -388,6 +388,7 @@ namespace smt {
|
|||
enode * n = *it3;
|
||||
if (is_uninterp_const(n->get_owner()) && m_context->is_relevant(n)) {
|
||||
func_decl * d = n->get_owner()->get_decl();
|
||||
TRACE("mg_top_sort", tout << d->get_name() << " " << (m_hidden_ufs.contains(d)?"hidden":"visible") << "\n";);
|
||||
if (m_hidden_ufs.contains(d)) continue;
|
||||
expr * val = get_value(n);
|
||||
m_model->register_decl(d, val);
|
||||
|
|
|
@ -724,8 +724,6 @@ namespace smt {
|
|||
}
|
||||
|
||||
void setup::setup_r_arith() {
|
||||
// to disable theory lra
|
||||
// m_context.register_plugin(alloc(smt::theory_mi_arith, m_manager, m_params));
|
||||
m_context.register_plugin(alloc(smt::theory_lra, m_manager, m_params));
|
||||
}
|
||||
|
||||
|
@ -789,6 +787,9 @@ namespace smt {
|
|||
case AS_OPTINF:
|
||||
m_context.register_plugin(alloc(smt::theory_inf_arith, m_manager, m_params));
|
||||
break;
|
||||
case AS_LRA:
|
||||
setup_r_arith();
|
||||
break;
|
||||
default:
|
||||
if (m_params.m_arith_int_only && int_only)
|
||||
m_context.register_plugin(alloc(smt::theory_i_arith, m_manager, m_params));
|
||||
|
|
|
@ -35,6 +35,7 @@ Revision History:
|
|||
#include "smt/smt_model_generator.h"
|
||||
#include "smt/arith_eq_adapter.h"
|
||||
#include "util/nat_set.h"
|
||||
#include "util/lp/nra_solver.h"
|
||||
#include "tactic/filter_model_converter.h"
|
||||
|
||||
namespace lp {
|
||||
|
@ -144,10 +145,10 @@ namespace smt {
|
|||
ast_manager& m;
|
||||
theory_arith_params& m_arith_params;
|
||||
arith_util a;
|
||||
|
||||
arith_eq_adapter m_arith_eq_adapter;
|
||||
vector<rational> m_columns;
|
||||
|
||||
|
||||
vector<rational> m_columns;
|
||||
// temporary values kept during internalization
|
||||
struct internalize_state {
|
||||
expr_ref_vector m_terms;
|
||||
|
@ -248,6 +249,8 @@ namespace smt {
|
|||
|
||||
unsigned m_num_conflicts;
|
||||
|
||||
scoped_ptr<nra::solver> m_nra;
|
||||
bool m_use_nra_model;
|
||||
|
||||
struct var_value_eq {
|
||||
imp & m_th;
|
||||
|
@ -291,6 +294,16 @@ namespace smt {
|
|||
//m_solver->settings().set_ostream(0);
|
||||
}
|
||||
|
||||
void ensure_nra() {
|
||||
if (!m_nra) {
|
||||
m_nra = alloc(nra::solver, *m_solver.get(), m.limit(), ctx().get_params());
|
||||
for (unsigned i = 0; i < m_scopes.size(); ++i) {
|
||||
m_nra->push();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void found_not_handled(expr* n) {
|
||||
m_not_handled = n;
|
||||
if (is_app(n) && is_underspecified(to_app(n))) {
|
||||
|
@ -366,6 +379,14 @@ namespace smt {
|
|||
terms[index] = n1;
|
||||
st.terms_to_internalize().push_back(n2);
|
||||
}
|
||||
else if (a.is_mul(n)) {
|
||||
theory_var v;
|
||||
internalize_mul(to_app(n), v, r);
|
||||
coeffs[index] *= r;
|
||||
coeffs[vars.size()] = coeffs[index];
|
||||
vars.push_back(v);
|
||||
++index;
|
||||
}
|
||||
else if (a.is_numeral(n, r)) {
|
||||
coeff += coeffs[index]*r;
|
||||
++index;
|
||||
|
@ -415,6 +436,44 @@ namespace smt {
|
|||
}
|
||||
}
|
||||
|
||||
void internalize_mul(app* t, theory_var& v, rational& r) {
|
||||
SASSERT(a.is_mul(t));
|
||||
bool _has_var = has_var(t);
|
||||
if (!_has_var) {
|
||||
internalize_args(t);
|
||||
mk_enode(t);
|
||||
}
|
||||
r = rational::one();
|
||||
rational r1;
|
||||
v = mk_var(t);
|
||||
svector<lean::var_index> vars;
|
||||
ptr_vector<expr> todo;
|
||||
todo.push_back(t);
|
||||
while (!todo.empty()) {
|
||||
expr* n = todo.back();
|
||||
todo.pop_back();
|
||||
expr* n1, *n2;
|
||||
if (a.is_mul(n, n1, n2)) {
|
||||
todo.push_back(n1);
|
||||
todo.push_back(n2);
|
||||
}
|
||||
else if (a.is_numeral(n, r1)) {
|
||||
r *= r1;
|
||||
}
|
||||
else {
|
||||
if (!ctx().e_internalized(n)) {
|
||||
ctx().internalize(n, false);
|
||||
}
|
||||
vars.push_back(get_var_index(mk_var(n)));
|
||||
}
|
||||
}
|
||||
TRACE("arith", tout << mk_pp(t, m) << "\n";);
|
||||
if (!_has_var) {
|
||||
ensure_nra();
|
||||
m_nra->add_monomial(get_var_index(v), vars.size(), vars.c_ptr());
|
||||
}
|
||||
}
|
||||
|
||||
enode * mk_enode(app * n) {
|
||||
if (ctx().e_internalized(n)) {
|
||||
return get_enode(n);
|
||||
|
@ -459,6 +518,14 @@ namespace smt {
|
|||
return m_arith_params.m_arith_reflect || is_underspecified(n);
|
||||
}
|
||||
|
||||
bool has_var(expr* n) {
|
||||
if (!ctx().e_internalized(n)) {
|
||||
return false;
|
||||
}
|
||||
enode* e = get_enode(n);
|
||||
return th.is_attached_to_var(e);
|
||||
}
|
||||
|
||||
theory_var mk_var(expr* n, bool internalize = true) {
|
||||
if (!ctx().e_internalized(n)) {
|
||||
ctx().internalize(n, false);
|
||||
|
@ -487,7 +554,7 @@ namespace smt {
|
|||
result = m_theory_var2var_index[v];
|
||||
}
|
||||
if (result == UINT_MAX) {
|
||||
result = m_solver->add_var(v);
|
||||
result = m_solver->add_var(v, false);
|
||||
m_theory_var2var_index.setx(v, result, UINT_MAX);
|
||||
m_var_index2theory_var.setx(result, v, UINT_MAX);
|
||||
m_var_trail.push_back(v);
|
||||
|
@ -658,7 +725,8 @@ namespace smt {
|
|||
m_num_conflicts(0),
|
||||
m_model_eqs(DEFAULT_HASHTABLE_INITIAL_CAPACITY, var_value_hash(*this), var_value_eq(*this)),
|
||||
m_solver(0),
|
||||
m_resource_limit(*this) {
|
||||
m_resource_limit(*this),
|
||||
m_use_nra_model(false) {
|
||||
}
|
||||
|
||||
~imp() {
|
||||
|
@ -815,6 +883,7 @@ namespace smt {
|
|||
s.m_underspecified_lim = m_underspecified.size();
|
||||
s.m_var_trail_lim = m_var_trail.size();
|
||||
if (!m_delay_constraints) m_solver->push();
|
||||
if (m_nra) m_nra->push();
|
||||
}
|
||||
|
||||
void pop_scope_eh(unsigned num_scopes) {
|
||||
|
@ -847,6 +916,7 @@ namespace smt {
|
|||
// VERIFY(l_false != make_feasible());
|
||||
m_new_bounds.reset();
|
||||
m_to_check.reset();
|
||||
if (m_nra) m_nra->pop(num_scopes);
|
||||
TRACE("arith", tout << "num scopes: " << num_scopes << " new scope level: " << m_scopes.size() << "\n";);
|
||||
}
|
||||
|
||||
|
@ -1166,18 +1236,41 @@ namespace smt {
|
|||
else if (m_solver->get_status() != lean::lp_status::OPTIMAL) {
|
||||
is_sat = make_feasible();
|
||||
}
|
||||
final_check_status st = FC_DONE;
|
||||
switch (is_sat) {
|
||||
case l_true:
|
||||
|
||||
if (delayed_assume_eqs()) {
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (assume_eqs()) {
|
||||
return FC_CONTINUE;
|
||||
}
|
||||
if (m_not_handled != 0) {
|
||||
return FC_GIVEUP;
|
||||
|
||||
switch (check_lia()) {
|
||||
case l_true:
|
||||
break;
|
||||
case l_false:
|
||||
return FC_CONTINUE;
|
||||
case l_undef:
|
||||
st = FC_GIVEUP;
|
||||
break;
|
||||
}
|
||||
return FC_DONE;
|
||||
|
||||
switch (check_nra()) {
|
||||
case l_true:
|
||||
break;
|
||||
case l_false:
|
||||
return FC_CONTINUE;
|
||||
case l_undef:
|
||||
st = FC_GIVEUP;
|
||||
break;
|
||||
}
|
||||
if (m_not_handled != 0) {
|
||||
st = FC_GIVEUP;
|
||||
}
|
||||
|
||||
return st;
|
||||
case l_false:
|
||||
set_conflict();
|
||||
return FC_CONTINUE;
|
||||
|
@ -1190,6 +1283,30 @@ namespace smt {
|
|||
return FC_GIVEUP;
|
||||
}
|
||||
|
||||
lbool check_lia() {
|
||||
if (m.canceled()) return l_undef;
|
||||
return l_true;
|
||||
}
|
||||
|
||||
lbool check_nra() {
|
||||
m_use_nra_model = false;
|
||||
if (m.canceled()) return l_undef;
|
||||
if (!m_nra) return l_true;
|
||||
if (!m_nra->need_check()) return l_true;
|
||||
lbool r = m_nra->check(m_explanation);
|
||||
switch (r) {
|
||||
case l_false:
|
||||
set_conflict1();
|
||||
break;
|
||||
case l_true:
|
||||
m_use_nra_model = true;
|
||||
// TBD: check equalities
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
/**
|
||||
\brief We must redefine this method, because theory of arithmetic contains
|
||||
|
@ -2197,11 +2314,15 @@ namespace smt {
|
|||
}
|
||||
|
||||
void set_conflict() {
|
||||
m_explanation.clear();
|
||||
m_solver->get_infeasibility_explanation(m_explanation);
|
||||
set_conflict1();
|
||||
}
|
||||
|
||||
void set_conflict1() {
|
||||
m_eqs.reset();
|
||||
m_core.reset();
|
||||
m_params.reset();
|
||||
m_explanation.clear();
|
||||
m_solver->get_infeasibility_explanation(m_explanation);
|
||||
// m_solver->shrink_explanation_to_minimum(m_explanation); // todo, enable when perf is fixed
|
||||
/*
|
||||
static unsigned cn = 0;
|
||||
|
@ -2252,7 +2373,17 @@ namespace smt {
|
|||
|
||||
model_value_proc * mk_value(enode * n, model_generator & mg) {
|
||||
theory_var v = n->get_th_var(get_id());
|
||||
return alloc(expr_wrapper_proc, m_factory->mk_value(get_value(v), m.get_sort(n->get_owner())));
|
||||
expr* o = n->get_owner();
|
||||
if (m_use_nra_model) {
|
||||
SASSERT(m_nra);
|
||||
app* e = a.mk_numeral(m_nra->value(m_theory_var2var_index[v]), a.is_int(o));
|
||||
return alloc(expr_wrapper_proc, e);
|
||||
}
|
||||
else {
|
||||
rational r = get_value(v);
|
||||
if (a.is_int(o) && !r.is_int()) r = floor(r);
|
||||
return alloc(expr_wrapper_proc, m_factory->mk_value(r, m.get_sort(o)));
|
||||
}
|
||||
}
|
||||
|
||||
bool get_value(enode* n, expr_ref& r) {
|
||||
|
@ -2278,6 +2409,7 @@ namespace smt {
|
|||
if (dump_lemmas()) {
|
||||
ctx().display_lemma_as_smt_problem(m_core.size(), m_core.c_ptr(), m_eqs.size(), m_eqs.c_ptr(), false_literal);
|
||||
}
|
||||
if (m_arith_params.m_arith_mode == AS_LRA) return true;
|
||||
context nctx(m, ctx().get_fparams(), ctx().get_params());
|
||||
add_background(nctx);
|
||||
bool result = l_true != nctx.check();
|
||||
|
@ -2290,6 +2422,7 @@ namespace smt {
|
|||
if (dump_lemmas()) {
|
||||
ctx().display_lemma_as_smt_problem(m_core.size(), m_core.c_ptr(), m_eqs.size(), m_eqs.c_ptr(), lit);
|
||||
}
|
||||
if (m_arith_params.m_arith_mode == AS_LRA) return true;
|
||||
context nctx(m, ctx().get_fparams(), ctx().get_params());
|
||||
m_core.push_back(~lit);
|
||||
add_background(nctx);
|
||||
|
@ -2301,6 +2434,7 @@ namespace smt {
|
|||
}
|
||||
|
||||
bool validate_eq(enode* x, enode* y) {
|
||||
if (m_arith_params.m_arith_mode == AS_LRA) return true;
|
||||
context nctx(m, ctx().get_fparams(), ctx().get_params());
|
||||
add_background(nctx);
|
||||
nctx.assert_expr(m.mk_not(m.mk_eq(x->get_owner(), y->get_owner())));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue