mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +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
				
			
		|  | @ -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 << ")"; | ||||
|     } | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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" | ||||
| 
 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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); | ||||
|  |  | |||
|  | @ -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()) | ||||
|             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; | ||||
|         } | ||||
|  |  | |||
|  | @ -1,6 +1,7 @@ | |||
| z3_add_component(solver | ||||
|   SOURCES | ||||
|     check_sat_result.cpp | ||||
|     check_logic.cpp | ||||
|     combined_solver.cpp | ||||
|     mus.cpp | ||||
|     parallel_tactic.cpp | ||||
|  |  | |||
|  | @ -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" | ||||
|  | @ -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(); } | ||||
|  |  | |||
|  | @ -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(); } | ||||
|  |  | |||
|  | @ -376,7 +376,6 @@ public: | |||
| }; | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| template<typename Ctx, typename T> | ||||
| class remove_obj_trail : public trail<Ctx> { | ||||
|     obj_hashtable<T>& m_table; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue