3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-07 18:05:21 +00:00

debug arith/mbi

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-11-02 12:13:19 -08:00
parent fb6e7e146b
commit ab199dedf9
22 changed files with 96 additions and 25 deletions

View file

@ -279,19 +279,18 @@ public:
display_child(n);
return;
}
if (to_app(n)->get_num_args() > depth && to_app(n)->get_num_args() > 16) {
display_child(n);
return;
}
unsigned num_args = to_app(n)->get_num_args();
if (num_args > 0)
m_out << "(";
display_name(to_app(n)->get_decl());
display_params(to_app(n)->get_decl());
for (unsigned i = 0; i < num_args; i++) {
for (unsigned i = 0; i < num_args && i < 16; i++) {
m_out << " ";
display(to_app(n)->get_arg(i), depth-1);
}
if (num_args >= 16)
m_out << " ...";
if (num_args > 0)
m_out << ")";
}

View file

@ -1,7 +1,6 @@
z3_add_component(cmd_context
SOURCES
basic_cmds.cpp
check_logic.cpp
cmd_context.cpp
cmd_context_to_goal.cpp
cmd_util.cpp

View file

@ -35,10 +35,10 @@ Notes:
#include "ast/rewriter/seq_rewriter.h"
#include "tactic/generic_model_converter.h"
#include "solver/solver.h"
#include "solver/check_logic.h"
#include "solver/progress_callback.h"
#include "cmd_context/pdecl.h"
#include "cmd_context/tactic_manager.h"
#include "cmd_context/check_logic.h"
#include "params/context_params.h"

View file

@ -104,6 +104,7 @@ namespace lp_api {
unsigned m_bound_propagations1;
unsigned m_bound_propagations2;
unsigned m_assert_diseq;
unsigned m_assert_eq;
unsigned m_gomory_cuts;
unsigned m_assume_eqs;
unsigned m_branch;
@ -123,6 +124,7 @@ namespace lp_api {
st.update("arith-bound-propagations-lp", m_bound_propagations1);
st.update("arith-bound-propagations-cheap", m_bound_propagations2);
st.update("arith-diseq", m_assert_diseq);
st.update("arith-eq", m_assert_eq);
st.update("arith-gomory-cuts", m_gomory_cuts);
st.update("arith-assume-eqs", m_assume_eqs);
st.update("arith-branch", m_branch);

View file

@ -424,6 +424,7 @@ namespace sat {
}
}
switch (num_lits) {
case 0:
set_conflict();

View file

@ -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);

View file

@ -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);

View file

@ -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);); }

View file

@ -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;
}

View file

@ -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);

View file

@ -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);
}
}

View file

@ -79,6 +79,8 @@ namespace q {
void init_search();
void finalize_model(model& mdl);
void collect_statistics(statistics& st) const;
};
}

View file

@ -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) {

View file

@ -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);

View file

@ -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;
}

View file

@ -118,7 +118,7 @@ namespace smt {
// after n1 and n2 are marked as relevant.
//
data d;
if (m_already_processed.find(n1, n2, d))
if (m_already_processed.find(n1, n2, d))
return;
TRACE("arith_eq_adapter_profile", tout << "mk #" << n1->get_owner_id() << " #" << n2->get_owner_id() << " " <<

View file

@ -1,6 +1,7 @@
z3_add_component(solver
SOURCES
check_sat_result.cpp
check_logic.cpp
combined_solver.cpp
mus.cpp
parallel_tactic.cpp

View file

@ -16,7 +16,7 @@ Author:
Revision History:
--*/
#include "cmd_context/check_logic.h"
#include "solver/check_logic.h"
#include "solver/smt_logics.h"
#include "ast/arith_decl_plugin.h"
#include "ast/array_decl_plugin.h"

View file

@ -62,7 +62,7 @@ public:
*/
virtual void operator()(goal_ref const & in, goal_ref_buffer& result) = 0;
virtual void collect_statistics(statistics & st) const {}
virtual void collect_statistics(statistics & st) const { }
virtual void reset_statistics() {}
virtual void cleanup() = 0;
virtual void reset() { cleanup(); }

View file

@ -39,8 +39,9 @@ public:
void insert(obj_pair const & p) { m_set.insert(p); }
bool insert_if_not_there(T1 * t1, T2 * t2) { return m_set.insert_if_not_there2(obj_pair(t1, t2)); }
bool insert_if_not_there(obj_pair const & p) { return m_set.insert_if_not_there2(p); }
void erase(T1 * t1, T2 * t2) { return m_set.erase(obj_pair(t1, t2)); }
void erase(obj_pair const & p) { return m_set.erase(p); }
void erase(T1 * t1, T2 * t2) { m_set.erase(obj_pair(t1, t2)); }
void erase(obj_pair const & p) { m_set.erase(p); }
void remove(obj_pair const & p) { erase(p); }
bool contains(T1 * t1, T2 * t2) const { return m_set.contains(obj_pair(t1, t2)); }
bool contains(obj_pair const & p) const { return m_set.contains(p); }
void reset() { m_set.reset(); }

View file

@ -376,7 +376,6 @@ public:
};
template<typename Ctx, typename T>
class remove_obj_trail : public trail<Ctx> {
obj_hashtable<T>& m_table;