mirror of
https://github.com/Z3Prover/z3
synced 2025-08-23 11:37:54 +00:00
debug arith/mbi
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
fb6e7e146b
commit
ab199dedf9
22 changed files with 96 additions and 25 deletions
|
@ -424,6 +424,7 @@ namespace sat {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
switch (num_lits) {
|
||||
case 0:
|
||||
set_conflict();
|
||||
|
|
|
@ -296,15 +296,34 @@ namespace arith {
|
|||
return lp::EQ;
|
||||
}
|
||||
|
||||
void solver::mk_eq_axiom(bool is_eq, theory_var v1, theory_var v2) {
|
||||
void solver::mk_eq_axiom(bool is_eq, euf::th_eq const& e) {
|
||||
theory_var v1 = e.v1();
|
||||
theory_var v2 = e.v2();
|
||||
if (is_bool(v1))
|
||||
return;
|
||||
force_push();
|
||||
expr* e1 = var2expr(v1);
|
||||
expr* e2 = var2expr(v2);
|
||||
if (e1->get_id() > e2->get_id())
|
||||
std::swap(e1, e2);
|
||||
|
||||
if (is_eq && m.are_equal(e1, e2))
|
||||
return;
|
||||
if (!is_eq && m.are_distinct(e1, e2))
|
||||
return;
|
||||
|
||||
if (is_eq) {
|
||||
++m_stats.m_assert_eq;
|
||||
euf::enode* n1 = var2enode(v1);
|
||||
euf::enode* n2 = var2enode(v2);
|
||||
lpvar w1 = register_theory_var_in_lar_solver(v1);
|
||||
lpvar w2 = register_theory_var_in_lar_solver(v2);
|
||||
auto cs = lp().add_equality(w1, w2);
|
||||
add_eq_constraint(cs.first, n1, n2);
|
||||
add_eq_constraint(cs.second, n1, n2);
|
||||
m_new_eq = true;
|
||||
return;
|
||||
}
|
||||
literal le, ge;
|
||||
if (a.is_numeral(e1))
|
||||
std::swap(e1, e2);
|
||||
|
@ -332,6 +351,7 @@ namespace arith {
|
|||
le = mk_literal(a.mk_le(diff, zero));
|
||||
ge = mk_literal(a.mk_ge(diff, zero));
|
||||
}
|
||||
++m_stats.m_assert_diseq;
|
||||
add_clause(~eq, le);
|
||||
add_clause(~eq, ge);
|
||||
add_clause(~le, ~ge, eq);
|
||||
|
|
|
@ -86,9 +86,10 @@ namespace arith {
|
|||
}
|
||||
|
||||
bool solver::unit_propagate() {
|
||||
if (m_new_bounds.empty() && m_asserted_qhead == m_asserted.size())
|
||||
if (!m_new_eq && m_new_bounds.empty() && m_asserted_qhead == m_asserted.size())
|
||||
return false;
|
||||
|
||||
m_new_eq = false;
|
||||
flush_bound_axioms();
|
||||
|
||||
unsigned qhead = m_asserted_qhead;
|
||||
|
@ -911,6 +912,8 @@ namespace arith {
|
|||
theory_var v = (i + start) % sz;
|
||||
if (is_bool(v))
|
||||
continue;
|
||||
if (!ctx.is_shared(var2enode(v)))
|
||||
continue;
|
||||
ensure_column(v);
|
||||
if (!can_get_ivalue(v))
|
||||
continue;
|
||||
|
@ -945,7 +948,7 @@ namespace arith {
|
|||
continue;
|
||||
if (n1->get_root() == n2->get_root())
|
||||
continue;
|
||||
literal eq = eq_internalize(n1->get_expr(), n2->get_expr());
|
||||
literal eq = eq_internalize(n1, n2);
|
||||
if (s().value(eq) != l_true)
|
||||
return true;
|
||||
}
|
||||
|
@ -1040,7 +1043,6 @@ namespace arith {
|
|||
SASSERT(m_nla->use_nra_model());
|
||||
auto t = get_tv(v);
|
||||
if (t.is_term()) {
|
||||
|
||||
m_todo_terms.push_back(std::make_pair(t, rational::one()));
|
||||
TRACE("nl_value", tout << "v" << v << " " << t.to_string() << "\n";);
|
||||
TRACE("nl_value", tout << "v" << v << " := w" << t.to_string() << "\n";
|
||||
|
@ -1193,8 +1195,13 @@ namespace arith {
|
|||
TRACE("arith", display(tout << "is-conflict: " << is_conflict << "\n"););
|
||||
for (auto const& ev : m_explanation)
|
||||
set_evidence(ev.ci(), m_core, m_eqs);
|
||||
DEBUG_CODE(
|
||||
if (is_conflict) {
|
||||
for (literal c : m_core) VERIFY(s().value(c) == l_false);
|
||||
for (auto p : m_eqs) VERIFY(p.first->get_root() == p.second->get_root());
|
||||
});
|
||||
for (auto const& eq : m_eqs)
|
||||
m_core.push_back(eq_internalize(eq.first->get_expr(), eq.second->get_expr()));
|
||||
m_core.push_back(eq_internalize(eq.first, eq.second));
|
||||
for (literal& c : m_core)
|
||||
c.neg();
|
||||
add_clause(m_core);
|
||||
|
|
|
@ -16,8 +16,8 @@ Author:
|
|||
--*/
|
||||
#pragma once
|
||||
|
||||
#include "util/obj_pair_set.h"
|
||||
#include "ast/ast_trail.h"
|
||||
#include "sat/smt/sat_th.h"
|
||||
#include "ast/arith_decl_plugin.h"
|
||||
#include "math/lp/lp_solver.h"
|
||||
#include "math/lp/lp_primal_simplex.h"
|
||||
|
@ -29,6 +29,7 @@ Author:
|
|||
#include "math/lp/lp_api.h"
|
||||
#include "math/polynomial/algebraic_numbers.h"
|
||||
#include "math/polynomial/polynomial.h"
|
||||
#include "sat/smt/sat_th.h"
|
||||
|
||||
namespace euf {
|
||||
class solver;
|
||||
|
@ -90,7 +91,7 @@ namespace arith {
|
|||
};
|
||||
int_hashtable<var_value_hash, var_value_eq> m_model_eqs;
|
||||
|
||||
|
||||
bool m_new_eq { false };
|
||||
|
||||
|
||||
// temporary values kept during internalization
|
||||
|
@ -303,7 +304,7 @@ namespace arith {
|
|||
void refine_bound(theory_var v, const lp::implied_bound& be);
|
||||
literal is_bound_implied(lp::lconstraint_kind k, rational const& value, api_bound const& b) const;
|
||||
void assert_bound(bool is_true, api_bound& b);
|
||||
void mk_eq_axiom(bool is_eq, theory_var v1, theory_var v2);
|
||||
void mk_eq_axiom(bool is_eq, euf::th_eq const& eq);
|
||||
void assert_idiv_mod_axioms(theory_var u, theory_var v, theory_var w, rational const& r);
|
||||
api_bound* mk_var_bound(sat::literal lit, theory_var v, lp_api::bound_kind bk, rational const& bound);
|
||||
lp::lconstraint_kind bound2constraint_kind(bool is_int, lp_api::bound_kind bk, bool is_true);
|
||||
|
@ -424,8 +425,8 @@ namespace arith {
|
|||
void collect_statistics(statistics& st) const override;
|
||||
euf::th_solver* clone(euf::solver& ctx) override;
|
||||
bool use_diseqs() const override { return true; }
|
||||
void new_eq_eh(euf::th_eq const& eq) override { mk_eq_axiom(true, eq.v1(), eq.v2()); }
|
||||
void new_diseq_eh(euf::th_eq const& de) override { mk_eq_axiom(false, de.v1(), de.v2()); }
|
||||
void new_eq_eh(euf::th_eq const& eq) override { mk_eq_axiom(true, eq); }
|
||||
void new_diseq_eh(euf::th_eq const& de) override { mk_eq_axiom(false, de); }
|
||||
bool unit_propagate() override;
|
||||
void init_model() override { init_variable_values(); }
|
||||
void finalize_model(model& mdl) override { DEBUG_CODE(dbg_finalize_model(mdl);); }
|
||||
|
|
|
@ -83,6 +83,7 @@ namespace euf {
|
|||
if (ext)
|
||||
return ext;
|
||||
ext = alloc(q::solver, *this, fid);
|
||||
m_qsolver = ext;
|
||||
add_solver(ext);
|
||||
return ext;
|
||||
}
|
||||
|
@ -364,11 +365,33 @@ namespace euf {
|
|||
}
|
||||
}
|
||||
|
||||
bool solver::is_self_propagated(th_eq const& e) {
|
||||
if (!e.is_eq())
|
||||
return false;
|
||||
|
||||
m_egraph.begin_explain();
|
||||
m_explain.reset();
|
||||
m_egraph.explain_eq<size_t>(m_explain, e.child(), e.root());
|
||||
m_egraph.end_explain();
|
||||
for (auto p : m_explain) {
|
||||
if (is_literal(p))
|
||||
return false;
|
||||
|
||||
size_t idx = get_justification(p);
|
||||
auto* ext = sat::constraint_base::to_extension(idx);
|
||||
if (ext->get_id() != e.id())
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void solver::propagate_th_eqs() {
|
||||
for (; m_egraph.has_th_eq() && !s().inconsistent() && !m_egraph.inconsistent(); m_egraph.next_th_eq()) {
|
||||
th_eq eq = m_egraph.get_th_eq();
|
||||
if (eq.is_eq())
|
||||
m_id2solver[eq.id()]->new_eq_eh(eq);
|
||||
if (eq.is_eq()) {
|
||||
if (!is_self_propagated(eq))
|
||||
m_id2solver[eq.id()]->new_eq_eh(eq);
|
||||
}
|
||||
else
|
||||
m_id2solver[eq.id()]->new_diseq_eh(eq);
|
||||
}
|
||||
|
@ -404,16 +427,22 @@ namespace euf {
|
|||
for (auto* e : m_solvers) {
|
||||
if (!m.inc())
|
||||
return sat::check_result::CR_GIVEUP;
|
||||
if (e == m_qsolver)
|
||||
continue;
|
||||
switch (e->check()) {
|
||||
case sat::check_result::CR_CONTINUE: cont = true; break;
|
||||
case sat::check_result::CR_GIVEUP: give_up = true; break;
|
||||
default: break;
|
||||
}
|
||||
if (s().inconsistent())
|
||||
return sat::check_result::CR_CONTINUE;
|
||||
}
|
||||
if (cont)
|
||||
return sat::check_result::CR_CONTINUE;
|
||||
if (give_up)
|
||||
return sat::check_result::CR_GIVEUP;
|
||||
if (m_qsolver)
|
||||
return m_qsolver->check();
|
||||
TRACE("after_search", s().display(tout););
|
||||
return sat::check_result::CR_DONE;
|
||||
}
|
||||
|
|
|
@ -93,6 +93,7 @@ namespace euf {
|
|||
scoped_ptr<euf::ackerman> m_ackerman;
|
||||
scoped_ptr<sat::dual_solver> m_dual_solver;
|
||||
user::solver* m_user_propagator{ nullptr };
|
||||
th_solver* m_qsolver { nullptr };
|
||||
|
||||
ptr_vector<expr> m_bool_var2expr;
|
||||
ptr_vector<size_t> m_explain;
|
||||
|
@ -147,6 +148,7 @@ namespace euf {
|
|||
// solving
|
||||
void propagate_literals();
|
||||
void propagate_th_eqs();
|
||||
bool is_self_propagated(th_eq const& e);
|
||||
void get_antecedents(literal l, constraint& j, literal_vector& r, bool probing);
|
||||
void new_diseq(enode* a, enode* b, literal lit);
|
||||
|
||||
|
|
|
@ -387,4 +387,9 @@ namespace q {
|
|||
m_plugins.set(fid, p);
|
||||
}
|
||||
|
||||
void mbqi::collect_statistics(statistics& st) const {
|
||||
if (m_solver)
|
||||
m_solver->collect_statistics(st);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -79,6 +79,8 @@ namespace q {
|
|||
void init_search();
|
||||
|
||||
void finalize_model(model& mdl);
|
||||
|
||||
void collect_statistics(statistics& st) const;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -60,6 +60,7 @@ namespace q {
|
|||
|
||||
void solver::collect_statistics(statistics& st) const {
|
||||
st.update("quantifier asserts", m_stats.m_num_quantifier_asserts);
|
||||
m_mbqi.collect_statistics(st);
|
||||
}
|
||||
|
||||
euf::th_solver* solver::clone(euf::solver& ctx) {
|
||||
|
|
|
@ -150,6 +150,7 @@ namespace euf {
|
|||
bool is_true(sat::literal a, sat::literal b, sat::literal c, sat::literal d) { return is_true(a) || is_true(b, c, c); }
|
||||
|
||||
sat::literal eq_internalize(expr* a, expr* b);
|
||||
sat::literal eq_internalize(enode* a, enode* b) { return eq_internalize(a->get_expr(), b->get_expr()); }
|
||||
|
||||
euf::enode* e_internalize(expr* e);
|
||||
euf::enode* mk_enode(expr* e, bool suppress_args = false);
|
||||
|
|
|
@ -208,6 +208,7 @@ public:
|
|||
}
|
||||
catch (z3_exception& ex) {
|
||||
(void)ex;
|
||||
proc.m_solver->collect_statistics(m_stats);
|
||||
TRACE("sat", tout << ex.msg() << "\n";);
|
||||
throw;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue