mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 19:52:29 +00:00 
			
		
		
		
	add bvmax tactic, add proviso for non-0 lower bounds in elim01
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									ea261c930d
								
							
						
					
					
						commit
						0181f0f9df
					
				
					 8 changed files with 121 additions and 14 deletions
				
			
		|  | @ -1376,6 +1376,9 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions | |||
|             throw cmd_exception(ex.msg()); | ||||
|         } | ||||
|         get_opt()->set_status(r); | ||||
|         if (r != l_false) { | ||||
|             get_opt()->display_assignment(regular_stream()); | ||||
|         } | ||||
|     } | ||||
|     else if (m_solver) { | ||||
|         m_check_sat_result = m_solver.get(); // solver itself stores the result.
 | ||||
|  | @ -1580,6 +1583,9 @@ void cmd_context::display_statistics(bool show_total_time, double total_time) { | |||
|     else if (m_solver) { | ||||
|         m_solver->collect_statistics(st); | ||||
|     } | ||||
|     else if (m_opt) { | ||||
|         m_opt->collect_statistics(st); | ||||
|     } | ||||
|     st.display_smt2(regular_stream()); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -121,6 +121,7 @@ public: | |||
|     virtual void cancel() = 0; | ||||
|     virtual lbool optimize() = 0; | ||||
|     virtual void set_hard_constraints(ptr_vector<expr> & hard) = 0; | ||||
|     virtual void display_assignment(std::ostream& out) = 0; | ||||
| }; | ||||
| 
 | ||||
| class cmd_context : public progress_callback, public tactic_manager, public ast_printer_context { | ||||
|  |  | |||
|  | @ -122,8 +122,7 @@ namespace opt { | |||
|         virtual void get_unsat_core(ptr_vector<expr> & r) {} | ||||
|         virtual std::string reason_unknown() const { return std::string("unknown"); } | ||||
| 
 | ||||
|         void display_assignment(std::ostream& out); | ||||
|         void display_range_assignment(std::ostream& out); | ||||
|         virtual void display_assignment(std::ostream& out); | ||||
|         static void collect_param_descrs(param_descrs & r); | ||||
|         void updt_params(params_ref& p); | ||||
| 
 | ||||
|  |  | |||
|  | @ -44,6 +44,7 @@ namespace opt { | |||
|         m_logic = l; | ||||
|         if (m_logic != symbol::null) | ||||
|             m_context.set_logic(m_logic); | ||||
|         m_params.m_relevancy_lvl = 0; | ||||
|     } | ||||
| 
 | ||||
|     unsigned opt_solver::m_dump_count = 0; | ||||
|  |  | |||
|  | @ -29,6 +29,9 @@ Notes: | |||
| #include "tactic.h" | ||||
| #include "model_smt2_pp.h" | ||||
| #include "pb_sls.h" | ||||
| #include "qfbv_tactic.h" | ||||
| #include "card2bv_tactic.h" | ||||
| #include "tactic2solver.h" | ||||
| 
 | ||||
| namespace smt { | ||||
| 
 | ||||
|  | @ -450,6 +453,7 @@ namespace opt { | |||
|         volatile bool    m_cancel; | ||||
|         params_ref       m_params; | ||||
|         opt_solver       m_solver; | ||||
|         ref<solver>      m_sat_solver; | ||||
|         scoped_ptr<imp>  m_imp; | ||||
|         smt::pb_sls      m_sls; | ||||
| 
 | ||||
|  | @ -511,6 +515,9 @@ namespace opt { | |||
|             if (m_engine == symbol("pwmax")) { | ||||
|                 return pb_solve(); | ||||
|             } | ||||
|             if (m_engine == symbol("bvmax")) { | ||||
|                 return pb2sat_solve(); | ||||
|             } | ||||
|             if (m_engine == symbol("wpm2")) { | ||||
|                 return wpm2_solve(); | ||||
|             } | ||||
|  | @ -520,7 +527,11 @@ namespace opt { | |||
|             if (m_engine == symbol("sls")) { | ||||
|                 return sls_solve(); | ||||
|             } | ||||
|             return incremental_solve(); | ||||
|             if (m_engine == symbol::null || m_engine == symbol("wmax")) { | ||||
|                 return incremental_solve(); | ||||
|             } | ||||
|             IF_VERBOSE(0, verbose_stream() << "(unknown engine " << m_engine << " using default 'wmax')\n";); | ||||
|             return incremental_solve();             | ||||
|         } | ||||
| 
 | ||||
|         rational get_lower() const { | ||||
|  | @ -535,6 +546,25 @@ namespace opt { | |||
|             mdl = m_model.get(); | ||||
|         } | ||||
| 
 | ||||
|         void set_cancel(bool f) { | ||||
|             if (m_sat_solver) { | ||||
|                 m_sat_solver->set_cancel(f); | ||||
|             } | ||||
|             m_sls.set_cancel(f); | ||||
|             m_cancel = f; | ||||
|             m_solver.set_cancel(f); | ||||
|             m_imp->m_cancel = f;         | ||||
|             m_imp->m_solver.set_cancel(f); | ||||
|         } | ||||
| 
 | ||||
|         void collect_statistics(statistics& st) const { | ||||
|             m_solver.collect_statistics(st); | ||||
|             if (m_sat_solver) { | ||||
|                 m_sat_solver->collect_statistics(st); | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         class scoped_ensure_theory { | ||||
|             smt::theory_weighted_maxsat* m_wth; | ||||
|         public: | ||||
|  | @ -732,7 +762,6 @@ namespace opt { | |||
| 
 | ||||
| 
 | ||||
|         // convert bounds constraint into pseudo-Boolean
 | ||||
| 
 | ||||
|         lbool pb_solve() { | ||||
|             pb_util u(m); | ||||
|             expr_ref fml(m), val(m); | ||||
|  | @ -778,6 +807,63 @@ namespace opt { | |||
|             return is_sat; | ||||
|         } | ||||
| 
 | ||||
|         //
 | ||||
|         // convert bounds constraint into pseudo-Boolean, 
 | ||||
|         // then treat pseudo-Booleans as bit-vectors and
 | ||||
|         // sorting circuits.
 | ||||
|         //
 | ||||
|         lbool pb2sat_solve() { | ||||
|             pb_util u(m); | ||||
|             expr_ref fml(m), val(m); | ||||
|             app_ref b(m); | ||||
|             expr_ref_vector nsoft(m); | ||||
|             m_lower = m_upper = rational::zero(); | ||||
|             tactic_ref pb2bv = mk_card2bv_tactic(m, m_params); | ||||
|             tactic_ref bv2sat = mk_qfbv_tactic(m, m_params); | ||||
|             tactic_ref tac = and_then(pb2bv.get(), bv2sat.get()); | ||||
|             m_sat_solver = mk_tactic2solver(m, tac.get(), m_params); | ||||
|             unsigned sz = s.get_num_assertions(); | ||||
|             for (unsigned i = 0; i < sz; ++i) { | ||||
|                 m_sat_solver->assert_expr(s.get_assertion(i)); | ||||
|             } | ||||
|             for (unsigned i = 0; i < m_soft.size(); ++i) { | ||||
|                 m_upper += m_weights[i]; | ||||
|                 b = m.mk_fresh_const("b", m.mk_bool_sort()); | ||||
|                 // TODO: s.mc().insert(b->get_decl());
 | ||||
|                 fml = m.mk_or(m_soft[i].get(), b); | ||||
|                 m_sat_solver->assert_expr(fml); | ||||
|                 nsoft.push_back(b); | ||||
|             } | ||||
|             lbool is_sat = l_true; | ||||
|             bool was_sat = false; | ||||
|             while (l_true == is_sat) { | ||||
|                 is_sat = m_sat_solver->check_sat(0,0); | ||||
|                 if (m_cancel) { | ||||
|                     is_sat = l_undef; | ||||
|                 } | ||||
|                 if (is_sat == l_true) { | ||||
|                     m_sat_solver->get_model(m_model); | ||||
|                     m_upper = rational::zero(); | ||||
|                     for (unsigned i = 0; i < m_soft.size(); ++i) { | ||||
|                         VERIFY(m_model->eval(nsoft[i].get(), val)); | ||||
|                         m_assignment[i] = !m.is_true(val); | ||||
|                         if (!m_assignment[i]) { | ||||
|                             m_upper += m_weights[i]; | ||||
|                         } | ||||
|                     }                     | ||||
|                     IF_VERBOSE(1, verbose_stream() << "(wmaxsat.pb with upper bound: " << m_upper << ")\n";); | ||||
|                     fml = m.mk_not(u.mk_ge(nsoft.size(), m_weights.c_ptr(), nsoft.c_ptr(), m_upper)); | ||||
|                     m_sat_solver->assert_expr(fml); | ||||
|                     was_sat = true; | ||||
|                 } | ||||
|             }             | ||||
|             if (is_sat == l_false && was_sat) { | ||||
|                 is_sat = l_true; | ||||
|                 m_lower = m_upper; | ||||
|             } | ||||
|             return is_sat; | ||||
|         } | ||||
| 
 | ||||
|         expr* mk_not(expr* e) { | ||||
|             if (m.is_not(e, e)) { | ||||
|                 return e; | ||||
|  | @ -1285,14 +1371,10 @@ namespace opt { | |||
|         return m_imp->m_assignment[idx]; | ||||
|     } | ||||
|     void wmaxsmt::set_cancel(bool f) { | ||||
|         m_imp->m_sls.set_cancel(f); | ||||
|         m_imp->m_cancel = f; | ||||
|         m_imp->m_solver.set_cancel(f); | ||||
|         m_imp->m_imp->m_cancel = f;         | ||||
|         m_imp->m_imp->m_solver.set_cancel(f); | ||||
|         m_imp->set_cancel(f); | ||||
|     } | ||||
|     void wmaxsmt::collect_statistics(statistics& st) const { | ||||
|         m_imp->m_solver.collect_statistics(st); | ||||
|         m_imp->collect_statistics(st); | ||||
|     } | ||||
|     void wmaxsmt::get_model(model_ref& mdl) { | ||||
|         m_imp->get_model(mdl); | ||||
|  |  | |||
|  | @ -686,7 +686,7 @@ namespace sat { | |||
|     //
 | ||||
|     // -----------------------
 | ||||
|     lbool solver::check() { | ||||
|         IF_VERBOSE(0, verbose_stream() << "(sat.sat-solver using the new SAT solver)\n";); | ||||
|         IF_VERBOSE(2, verbose_stream() << "(sat.sat-solver using the new SAT solver)\n";); | ||||
|         SASSERT(scope_lvl() == 0); | ||||
| #ifdef CLONE_BEFORE_SOLVING | ||||
|         if (m_mc.empty()) { | ||||
|  |  | |||
|  | @ -1558,6 +1558,8 @@ namespace smt { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     static unsigned s_min_l_size = UINT_MAX; | ||||
|          | ||||
|     //
 | ||||
|     // modeled after sat_solver/smt_context
 | ||||
|     //
 | ||||
|  | @ -1731,6 +1733,12 @@ namespace smt { | |||
|         m_lemma.prune(false); | ||||
| 
 | ||||
|         IF_VERBOSE(4, display(verbose_stream() << "lemma2: ", m_lemma);); | ||||
|         //unsigned l_size = m_ineq_literals.size() + ((is_true==l_false)?0:m_lemma.size());
 | ||||
|         //if (s_min_l_size >= l_size) {
 | ||||
|         //    verbose_stream() << "(pb.conflict min size: " << l_size << ")\n";
 | ||||
|         //    s_min_l_size = l_size;        
 | ||||
|         //}
 | ||||
|         //IF_VERBOSE(1, verbose_stream() << "(pb.conflict " << m_ineq_literals.size() << " " << m_lemma.size() << "\n";);
 | ||||
|         switch(is_true) { | ||||
|         case l_true: | ||||
|             UNREACHABLE(); | ||||
|  |  | |||
|  | @ -167,6 +167,7 @@ public: | |||
|         expr_ref_vector axioms(m); | ||||
|         bounds(*g); | ||||
|          | ||||
|         rational zero(0); | ||||
|         bound_manager::iterator bit = bounds.begin(), bend = bounds.end(); | ||||
|         for (; bit != bend; ++bit) { | ||||
|             if (!is_app(*bit)) continue; | ||||
|  | @ -174,9 +175,14 @@ public: | |||
|             bool s1, s2; | ||||
|             rational lo, hi; | ||||
|             if (a.is_int(x) &&  | ||||
|                 bounds.has_lower(x, lo, s1) && !s1 && lo.is_zero() && | ||||
|                 bounds.has_upper(x, hi, s2) && !s2 && hi <= m_max_hi) { | ||||
|                 add_variable(b2i, sub, x, hi.get_unsigned(), axioms); | ||||
|                 bounds.has_lower(x, lo, s1) && !s1 && zero <= lo && | ||||
|                 bounds.has_upper(x, hi, s2) && !s2 && hi <= m_max_hi && lo <= hi) { | ||||
|                 add_variable(b2i, sub, x, lo.get_unsigned(), hi.get_unsigned(), axioms); | ||||
|             } | ||||
|             else if (a.is_int(x)) { | ||||
|                 TRACE("pb", tout << "Not adding variable " << mk_pp(x, m) << " has lower: "  | ||||
|                       << bounds.has_lower(x, lo, s1) << " " << lo << " has upper: "  | ||||
|                       << bounds.has_upper(x, hi, s2) << " " << hi << "\n";); | ||||
|             } | ||||
|         } | ||||
|                 | ||||
|  | @ -209,6 +215,7 @@ public: | |||
|     void add_variable(bool2int_model_converter* b2i, | ||||
|                       expr_safe_replace& sub, | ||||
|                       app* x, | ||||
|                       unsigned min_value, | ||||
|                       unsigned max_value, | ||||
|                       expr_ref_vector& axioms) { | ||||
|         std::string name = x->get_decl()->get_name().str(); | ||||
|  | @ -242,6 +249,9 @@ public: | |||
|         if ((max_value & (max_value + 1)) != 0) { | ||||
|             axioms.push_back(a.mk_le(sum, a.mk_numeral(rational(max_value), true))); | ||||
|         } | ||||
|         if (min_value > 0) { | ||||
|             axioms.push_back(a.mk_ge(sum, a.mk_numeral(rational(min_value), true))); | ||||
|         } | ||||
|     } | ||||
|                        | ||||
| }; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue