mirror of
				https://github.com/Z3Prover/z3
				synced 2025-10-31 11:42:28 +00:00 
			
		
		
		
	adding annotation to logging to show number of columns and rows, adding dual propagation sketch
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									aae37c2317
								
							
						
					
					
						commit
						761c7d9a40
					
				
					 12 changed files with 152 additions and 303 deletions
				
			
		|  | @ -506,6 +506,7 @@ namespace datalog { | |||
|             virtual unsigned get_size_estimate_rows() const { return UINT_MAX; } | ||||
|             virtual unsigned get_size_estimate_bytes() const { return UINT_MAX; } | ||||
|             virtual bool knows_exact_size() const { return false; } | ||||
|             unsigned num_columns() const { return get_signature().size(); } | ||||
| 
 | ||||
|             virtual void display(std::ostream & out) const = 0; | ||||
|         }; | ||||
|  |  | |||
|  | @ -62,6 +62,10 @@ namespace datalog { | |||
|         return dynamic_cast<rel_context&>(*m_context.get_rel_context());  | ||||
|     } | ||||
| 
 | ||||
|     rel_context const& execution_context::get_rel_context() const {  | ||||
|         return dynamic_cast<rel_context const&>(*m_context.get_rel_context());  | ||||
|     } | ||||
| 
 | ||||
|     struct compare_size_proc { | ||||
|         typedef std::pair<unsigned, unsigned> pr; | ||||
|         bool operator()(pr const& a, pr const& b) const { | ||||
|  | @ -164,21 +168,21 @@ namespace datalog { | |||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     void instruction::display_indented(rel_context_base const & _ctx, std::ostream & out, std::string indentation) const { | ||||
|     void instruction::display_indented(execution_context const & _ctx, std::ostream & out, std::string indentation) const { | ||||
|         out << indentation; | ||||
|         rel_context const& ctx = dynamic_cast<const rel_context&>(_ctx); | ||||
|         display_head_impl(ctx, out); | ||||
|         rel_context const& ctx = _ctx.get_rel_context(); | ||||
|         display_head_impl(_ctx, out); | ||||
|         if (ctx.output_profile()) { | ||||
|             out << " {"; | ||||
|             output_profile(out); | ||||
|             out << '}'; | ||||
|         } | ||||
|         out << "\n"; | ||||
|         display_body_impl(ctx, out, indentation); | ||||
|         display_body_impl(_ctx, out, indentation); | ||||
|     } | ||||
| 
 | ||||
|     void instruction::log_verbose(execution_context& ctx) { | ||||
|         IF_VERBOSE(2, display(ctx.get_rel_context(), verbose_stream());); | ||||
|         IF_VERBOSE(2, display(ctx, verbose_stream());); | ||||
|     } | ||||
| 
 | ||||
|     class instr_io : public instruction { | ||||
|  | @ -217,7 +221,7 @@ namespace datalog { | |||
|         virtual void make_annotations(execution_context & ctx) { | ||||
|             ctx.set_register_annotation(m_reg, m_pred->get_name().bare_str()); | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             const char * rel_name = m_pred->get_name().bare_str(); | ||||
|             if (m_store) { | ||||
|                 out << "store " << m_reg << " into " << rel_name; | ||||
|  | @ -248,7 +252,7 @@ namespace datalog { | |||
|         virtual void make_annotations(execution_context & ctx) { | ||||
|             ctx.set_register_annotation(m_reg, "alloc"); | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "dealloc " << m_reg; | ||||
|         } | ||||
|     }; | ||||
|  | @ -283,7 +287,7 @@ namespace datalog { | |||
|                 ctx.set_register_annotation(m_src, str); | ||||
|             } | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << (m_clone ? "clone " : "move ") << m_src << " into " << m_tgt; | ||||
|         } | ||||
|     }; | ||||
|  | @ -340,11 +344,11 @@ namespace datalog { | |||
|         virtual void make_annotations(execution_context & ctx) { | ||||
|             m_body->make_annotations(ctx); | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const & ctx, std::ostream & out) const { | ||||
|             out << "while"; | ||||
|             print_container(m_controls, out); | ||||
|         } | ||||
|         virtual void display_body_impl(rel_context_base const & ctx, std::ostream & out, std::string indentation) const { | ||||
|         virtual void display_body_impl(execution_context const & ctx, std::ostream & out, std::string indentation) const { | ||||
|             m_body->display_indented(ctx, out, indentation+"    "); | ||||
|         } | ||||
|     }; | ||||
|  | @ -409,7 +413,7 @@ namespace datalog { | |||
|             ctx.get_register_annotation(m_rel1, a1); | ||||
|             ctx.set_register_annotation(m_res, "join " + a1 + " " + a2); | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const & ctx, std::ostream & out) const { | ||||
|             out << "join " << m_rel1; | ||||
|             print_container(m_cols1, out); | ||||
|             out << " and " << m_rel2; | ||||
|  | @ -460,9 +464,9 @@ namespace datalog { | |||
|             a << "filter_equal " << m_col << " val: " << ctx.get_rel_context().get_rmanager().to_nice_string(m_value); | ||||
|             ctx.set_register_annotation(m_reg, a.str()); | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "filter_equal " << m_reg << " col: " << m_col << " val: " | ||||
|                 << ctx.get_rmanager().to_nice_string(m_value); | ||||
|                 << ctx.get_rel_context().get_rmanager().to_nice_string(m_value); | ||||
|         } | ||||
|     }; | ||||
| 
 | ||||
|  | @ -504,7 +508,7 @@ namespace datalog { | |||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "filter_identical " << m_reg << " "; | ||||
|             print_container(m_cols, out); | ||||
|         } | ||||
|  | @ -552,7 +556,7 @@ namespace datalog { | |||
| 
 | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "filter_interpreted " << m_reg << " using " | ||||
|                 << mk_pp(m_cond, m_cond.get_manager()); | ||||
|         } | ||||
|  | @ -609,7 +613,7 @@ namespace datalog { | |||
|             return true; | ||||
|         } | ||||
| 
 | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "filter_interpreted_and_project " << m_src << " into " << m_res; | ||||
|             out << " using " << mk_pp(m_cond, m_cond.get_manager()); | ||||
|             out << " deleting columns "; | ||||
|  | @ -726,7 +730,7 @@ namespace datalog { | |||
|             } | ||||
|             ctx.set_register_annotation(m_delta, str);             | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << (m_widen ? "widen " : "union ") << m_src << " into " << m_tgt; | ||||
|             if (m_delta!=execution_context::void_register) { | ||||
|                 out << " with delta " << m_delta; | ||||
|  | @ -782,7 +786,7 @@ namespace datalog { | |||
| 
 | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << (m_projection ? "project " : "rename ") << m_src << " into " << m_tgt; | ||||
|             out << (m_projection ? " deleting columns " : " with cycle "); | ||||
|             print_container(m_cols, out); | ||||
|  | @ -846,10 +850,20 @@ namespace datalog { | |||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             relation_base const* r1 = ctx.reg(m_rel1); | ||||
|             relation_base const* r2 = ctx.reg(m_rel2); | ||||
|             out << "join_project " << m_rel1;             | ||||
|             if (r1) { | ||||
|                 out << ":" << r1->num_columns(); | ||||
|                 out << "-" << r1->get_size_estimate_rows(); | ||||
|             } | ||||
|             print_container(m_cols1, out); | ||||
|             out << " and " << m_rel2; | ||||
|             if (r2) { | ||||
|                 out << ":" << r2->num_columns(); | ||||
|                 out << "-" << r2->get_size_estimate_rows(); | ||||
|             } | ||||
|             print_container(m_cols2, out); | ||||
|             out << " into " << m_res << " removing columns "; | ||||
|             print_container(m_removed_cols, out); | ||||
|  | @ -908,9 +922,9 @@ namespace datalog { | |||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "select_equal_and_project " << m_src <<" into " << m_result << " col: " << m_col  | ||||
|                 << " val: " << ctx.get_rmanager().to_nice_string(m_value); | ||||
|                 << " val: " << ctx.get_rel_context().get_rmanager().to_nice_string(m_value); | ||||
|         } | ||||
|         virtual void make_annotations(execution_context & ctx) { | ||||
|             std::stringstream s; | ||||
|  | @ -965,7 +979,7 @@ namespace datalog { | |||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "filter_by_negation on " << m_tgt; | ||||
|             print_container(m_cols1, out); | ||||
|             out << " with " << m_neg_rel; | ||||
|  | @ -1004,10 +1018,10 @@ namespace datalog { | |||
|             ctx.set_reg(m_tgt, rel); | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "mk_unary_singleton into " << m_tgt << " sort:"  | ||||
|                 << ctx.get_rmanager().to_nice_string(m_sig[0]) << " val:"  | ||||
|                 <<  ctx.get_rmanager().to_nice_string(m_sig[0], m_fact[0]); | ||||
|                 << ctx.get_rel_context().get_rmanager().to_nice_string(m_sig[0]) << " val:"  | ||||
|                 << ctx.get_rel_context().get_rmanager().to_nice_string(m_sig[0], m_fact[0]); | ||||
|         } | ||||
|         virtual void make_annotations(execution_context & ctx) { | ||||
|             std::string s; | ||||
|  | @ -1035,9 +1049,9 @@ namespace datalog { | |||
|             ctx.set_reg(m_tgt, ctx.get_rel_context().get_rmanager().mk_full_relation(m_sig, m_pred)); | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "mk_total into " << m_tgt << " sort:"  | ||||
|                 << ctx.get_rmanager().to_nice_string(m_sig); | ||||
|                 << ctx.get_rel_context().get_rmanager().to_nice_string(m_sig); | ||||
|         } | ||||
|         virtual void make_annotations(execution_context & ctx) { | ||||
|             std::string s; | ||||
|  | @ -1061,7 +1075,7 @@ namespace datalog { | |||
|             ctx.get_rel_context().get_rmanager().mark_saturated(m_pred); | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "mark_saturated " << m_pred->get_name().bare_str(); | ||||
|         } | ||||
|         virtual void make_annotations(execution_context & ctx) {             | ||||
|  | @ -1085,7 +1099,7 @@ namespace datalog { | |||
|             } | ||||
|             return true; | ||||
|         } | ||||
|         virtual void display_head_impl(rel_context const& ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const& ctx, std::ostream & out) const { | ||||
|             out << "instr_assert_signature of " << m_tgt << " signature:"; | ||||
|             print_container(m_sig, out); | ||||
|         } | ||||
|  | @ -1166,14 +1180,14 @@ namespace datalog { | |||
|         } | ||||
|     } | ||||
| 
 | ||||
|     void instruction_block::display_indented(rel_context_base const& _ctx, std::ostream & out, std::string indentation) const { | ||||
|         rel_context const& ctx = dynamic_cast<rel_context const&>(_ctx); | ||||
|     void instruction_block::display_indented(execution_context const& _ctx, std::ostream & out, std::string indentation) const { | ||||
|         rel_context const& ctx = _ctx.get_rel_context(); | ||||
|         instr_seq_type::const_iterator it = m_data.begin(); | ||||
|         instr_seq_type::const_iterator end = m_data.end(); | ||||
|         for(; it!=end; ++it) { | ||||
|             instruction * i = (*it); | ||||
|             if (i->passes_output_thresholds(ctx.get_context()) || i->being_recorded()) { | ||||
|                 i->display_indented(ctx, out, indentation); | ||||
|                 i->display_indented(_ctx, out, indentation); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -73,6 +73,7 @@ namespace datalog { | |||
|         void reset(); | ||||
| 
 | ||||
|         rel_context & get_rel_context(); | ||||
|         rel_context const & get_rel_context() const; | ||||
| 
 | ||||
|         void set_timelimit(unsigned time_in_ms); | ||||
|         void reset_timelimit(); | ||||
|  | @ -224,7 +225,7 @@ namespace datalog { | |||
| 
 | ||||
|            The newline character at the end should not be printed. | ||||
|         */ | ||||
|         virtual void display_head_impl(rel_context const & ctx, std::ostream & out) const { | ||||
|         virtual void display_head_impl(execution_context const & ctx, std::ostream & out) const { | ||||
|             out << "<instruction>"; | ||||
|         } | ||||
|         /**
 | ||||
|  | @ -232,7 +233,7 @@ namespace datalog { | |||
| 
 | ||||
|            Each line must be prepended by \c indentation and ended by a newline character. | ||||
|         */ | ||||
|         virtual void display_body_impl(rel_context_base const & ctx, std::ostream & out, std::string indentation) const {} | ||||
|         virtual void display_body_impl(execution_context const & ctx, std::ostream & out, std::string indentation) const {} | ||||
|         void log_verbose(execution_context& ctx); | ||||
| 
 | ||||
|     public: | ||||
|  | @ -245,10 +246,10 @@ namespace datalog { | |||
| 
 | ||||
|         virtual void make_annotations(execution_context & ctx)  = 0; | ||||
| 
 | ||||
|         void display(rel_context_base const& ctx, std::ostream & out) const { | ||||
|         void display(execution_context const& ctx, std::ostream & out) const { | ||||
|             display_indented(ctx, out, ""); | ||||
|         } | ||||
|         void display_indented(rel_context_base const & ctx, std::ostream & out, std::string indentation) const; | ||||
|         void display_indented(execution_context const & ctx, std::ostream & out, std::string indentation) const; | ||||
| 
 | ||||
|         static instruction * mk_load(ast_manager & m, func_decl * pred, reg_idx tgt); | ||||
|         /**
 | ||||
|  | @ -353,10 +354,10 @@ namespace datalog { | |||
| 
 | ||||
|         void make_annotations(execution_context & ctx); | ||||
| 
 | ||||
|         void display(rel_context_base const & ctx, std::ostream & out) const { | ||||
|         void display(execution_context const & ctx, std::ostream & out) const { | ||||
|             display_indented(ctx, out, ""); | ||||
|         } | ||||
|         void display_indented(rel_context_base const & ctx, std::ostream & out, std::string indentation) const; | ||||
|         void display_indented(execution_context const & ctx, std::ostream & out, std::string indentation) const; | ||||
| 
 | ||||
|         unsigned num_instructions() const { return m_data.size(); } | ||||
|     }; | ||||
|  |  | |||
|  | @ -630,7 +630,7 @@ namespace datalog { | |||
| 
 | ||||
|         out << "\n--------------\n"; | ||||
|         out << "Instructions\n"; | ||||
|         m_code.display(*this, out); | ||||
|         m_code.display(m_ectx, out); | ||||
| 
 | ||||
|         out << "\n--------------\n"; | ||||
|         out << "Big relations\n"; | ||||
|  |  | |||
|  | @ -56,6 +56,7 @@ class inc_sat_solver : public solver { | |||
|     expr_dependency_ref m_dep_core; | ||||
|     expr_ref_vector     m_soft; | ||||
|     vector<rational>    m_weights; | ||||
|     bool                m_soft_assumptions; | ||||
| 
 | ||||
| 
 | ||||
|     typedef obj_map<expr, sat::literal> dep2asm_t; | ||||
|  | @ -69,7 +70,8 @@ public: | |||
|         m_map(m), | ||||
|         m_num_scopes(0),  | ||||
|         m_dep_core(m), | ||||
|         m_soft(m) { | ||||
|         m_soft(m), | ||||
|         m_soft_assumptions(false) { | ||||
|         m_params.set_bool("elim_vars", false); | ||||
|         m_solver.updt_params(m_params); | ||||
|         params_ref simp2_p = p; | ||||
|  | @ -177,6 +179,7 @@ public: | |||
|         m_params = p; | ||||
|         m_params.set_bool("elim_vars", false); | ||||
|         m_solver.updt_params(m_params); | ||||
|         m_soft_assumptions = m_params.get_bool("soft_assumptions", false); | ||||
|         m_optimize_model = m_params.get_bool("optimize_model", false); | ||||
|     }     | ||||
|     virtual void collect_statistics(statistics & st) const { | ||||
|  | @ -355,7 +358,7 @@ private: | |||
|         dep2asm_t::iterator it = dep2asm.begin(), end = dep2asm.end(); | ||||
|         for (; it != end; ++it) { | ||||
|             sat::literal lit = it->m_value; | ||||
|             if (sat::value_at(lit, ll_m) != l_true) { | ||||
|             if (!m_soft_assumptions && sat::value_at(lit, ll_m) != l_true) { | ||||
|                 IF_VERBOSE(0, verbose_stream() << mk_pp(it->m_key, m) << " does not evaluate to true\n"; | ||||
|                            verbose_stream() << m_asms << "\n"; | ||||
|                            m_solver.display_assignment(verbose_stream()); | ||||
|  |  | |||
|  | @ -11,7 +11,6 @@ Abstract: | |||
| 
 | ||||
|     - mus:     max-sat algorithm by Nina and Bacchus, AAAI 2014. | ||||
|     - mus-mss: based on dual refinement of bounds. | ||||
|     - mss:     based on maximal satisfying sets (only). | ||||
| 
 | ||||
|     MaxRes is a core-guided approach to maxsat. | ||||
|     MusMssMaxRes extends the core-guided approach by | ||||
|  | @ -71,11 +70,19 @@ using namespace opt; | |||
| class maxres : public maxsmt_solver_base { | ||||
| public: | ||||
|     enum strategy_t { | ||||
|         s_mus, | ||||
|         s_mus_mss, | ||||
|         s_mss | ||||
|         s_primal, | ||||
|         s_primal_dual | ||||
|     }; | ||||
| private: | ||||
|     struct stats { | ||||
|         unsigned m_num_cores; | ||||
|         unsigned m_num_cs; | ||||
|         stats() { reset(); } | ||||
|         void reset() { | ||||
|             memset(this, 0, sizeof(*this)); | ||||
|         } | ||||
|     }; | ||||
|     stats            m_stats; | ||||
|     expr_ref_vector  m_B; | ||||
|     expr_ref_vector  m_asms;     | ||||
|     expr_ref_vector  m_defs; | ||||
|  | @ -167,7 +174,7 @@ public: | |||
|         trace_bounds("maxres"); | ||||
|         while (m_lower < m_upper) { | ||||
|             TRACE("opt",  | ||||
|                   display_vec(tout, m_asms.size(), m_asms.c_ptr()); | ||||
|                   display_vec(tout, m_asms); | ||||
|                   s().display(tout); | ||||
|                   tout << "\n"; | ||||
|                   display(tout); | ||||
|  | @ -194,159 +201,51 @@ public: | |||
|         return l_true; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     lbool mss_solver() { | ||||
|     lbool primal_dual_solver() { | ||||
|         init(); | ||||
|         init_local(); | ||||
|         sls(); | ||||
|         set_mus(false); | ||||
|         exprs mcs; | ||||
|         set_soft_assumptions(); | ||||
|         lbool is_sat = l_true; | ||||
|         while (m_lower < m_upper && is_sat == l_true) {             | ||||
|             trace_bounds("maxres"); | ||||
|         trace_bounds("max_res"); | ||||
|         exprs cs; | ||||
|         while (m_lower < m_upper) { | ||||
| #if 0 | ||||
|             expr_ref_vector asms(m_asms); | ||||
|             sort_assumptions(asms); | ||||
|             is_sat = s().check_sat(asms.size(), asms.c_ptr()); | ||||
| #else | ||||
|             is_sat = check_sat_hill_climb(m_asms); | ||||
| #endif | ||||
|             if (m_cancel) { | ||||
|                 return l_undef; | ||||
|             } | ||||
|             vector<exprs> cores; | ||||
|             exprs mss;        | ||||
|             model_ref mdl; | ||||
|             expr_ref tmp(m); | ||||
|             mcs.reset(); | ||||
|             s().get_model(mdl); | ||||
|             update_assignment(mdl.get()); | ||||
| 
 | ||||
|             exprs cs; | ||||
|             get_current_correction_set(mdl.get(), cs); | ||||
|             process_sat(cs); | ||||
| 
 | ||||
| #if 0 | ||||
|             is_sat = get_mss(mdl.get(), cores, mss, mcs); | ||||
|              | ||||
|             switch (is_sat) { | ||||
|             case l_true:  | ||||
|                 get_current_correction_set(cs); | ||||
|                 IF_VERBOSE(2, display_vec(verbose_stream() << "correction set: ", cs);); | ||||
|                 if (cs.empty()) { | ||||
|                     m_found_feasible_optimum = m_model.get() != 0; | ||||
|                     m_lower = m_upper; | ||||
|                 } | ||||
|                 else { | ||||
|                     process_sat(cs); | ||||
|                 } | ||||
|                 break; | ||||
|             case l_false: | ||||
|                 is_sat = process_unsat(); | ||||
|                 if (is_sat != l_true) return is_sat;                 | ||||
|                 break; | ||||
|             case l_undef: | ||||
|                 return l_undef; | ||||
|             case l_false: | ||||
|                 m_lower = m_upper; | ||||
|                 return l_true; | ||||
|             case l_true:                  | ||||
|                 process_sat(mcs); | ||||
|                 get_mss_model(); | ||||
|                 break;             | ||||
|             } | ||||
| #endif | ||||
|             if (m_lower < m_upper) { | ||||
|                 is_sat = s().check_sat(0, 0); | ||||
|             } | ||||
|         } | ||||
|         m_lower = m_upper; | ||||
|         return l_true; | ||||
|     } | ||||
| 
 | ||||
|     /**
 | ||||
|        Plan: | ||||
|        - Get maximal set of disjoint cores. | ||||
|        - Update the lower bound using the cores. | ||||
|        - As a side-effect find a satisfying assignment that has maximal weight. | ||||
|          (during core minimization several queries are bound to be SAT, | ||||
|          those can be used to boot-strap the MCS search). | ||||
|        - Use the best satisfying assignment from the MUS search to find an MCS of least weight. | ||||
|        - Update the upper bound using the MCS. | ||||
|        - Update the soft constraints using first the cores. | ||||
|        - Then update the resulting soft constraints using the evaluation of the MCS/MSS  | ||||
|        - Add a cardinality constraint to force new satisfying assignments to improve  | ||||
|          the new upper bound. | ||||
|        - In every iteration, the lower bound is improved using the cores. | ||||
|        - In every iteration, the upper bound is improved using the MCS. | ||||
|        - Optionally: add a cardinality constraint to prune the upper bound. | ||||
|         | ||||
|        What are the corner cases: | ||||
|        - suppose that cost of cores adds up to current upper bound. | ||||
|          -> it means that each core is a unit (?) | ||||
| 
 | ||||
|        TBD: | ||||
|        - Block upper bound using wmax or pb constraint, or in case of | ||||
|          unweighted constraints using incremental tricks. | ||||
|        - Throttle when correction set gets added based on its size. | ||||
|          Suppose correction set is huge. Do we really need it? | ||||
|         | ||||
|     */ | ||||
|     lbool mus_mss_solver() { | ||||
|         init(); | ||||
|         init_local(); | ||||
|         sls(); | ||||
|         vector<exprs> cores; | ||||
|         m_mus.set_soft(m_soft.size(), m_soft.c_ptr(), m_weights.c_ptr()); | ||||
|         lbool is_sat = l_true; | ||||
|         while (m_lower < m_upper && is_sat == l_true) {             | ||||
|             TRACE("opt",  | ||||
|                   display_vec(tout, m_asms.size(), m_asms.c_ptr()); | ||||
|                   s().display(tout); | ||||
|                   tout << "\n"; | ||||
|                   display(tout); | ||||
|                   ); | ||||
|             lbool is_sat = check_sat_hill_climb(m_asms); | ||||
|             if (m_cancel) { | ||||
|                 return l_undef; | ||||
|             } | ||||
|             switch (is_sat) { | ||||
|             case l_true:  | ||||
|                 found_optimum(); | ||||
|                 return l_true; | ||||
|             case l_false: | ||||
|                 is_sat = get_cores(cores); | ||||
|                 break; | ||||
|             default: | ||||
|                 break; | ||||
|             } | ||||
|             if (is_sat == l_undef) { | ||||
|                 return l_undef; | ||||
|             } | ||||
|             SASSERT((is_sat == l_false) == cores.empty()); | ||||
|             SASSERT((is_sat == l_true) == !cores.empty()); | ||||
|             if (cores.empty()) { | ||||
|                 break; | ||||
|             }            | ||||
| 
 | ||||
|             //
 | ||||
|             // There is a best model, retrieve 
 | ||||
|             // it from the previous core calls.
 | ||||
|             //
 | ||||
|             model_ref mdl; | ||||
|             get_mus_model(mdl); | ||||
| 
 | ||||
|             // 
 | ||||
|             // Extend the current model to a (maximal)
 | ||||
|             // assignment extracting the ss and cs.
 | ||||
|             // ss - satisfying subset
 | ||||
|             // cs - correction set (complement of ss).
 | ||||
|             //
 | ||||
|             if (m_maximize_assignment && mdl.get()) { | ||||
|                 exprs ss, cs; | ||||
|                 is_sat = get_mss(mdl.get(), cores, ss, cs); | ||||
|                 if (is_sat != l_true) return is_sat; | ||||
|                 get_mss_model(); | ||||
|             } | ||||
|             //
 | ||||
|             // block the hard constraints corresponding to the cores.
 | ||||
|             // block the soft constraints corresponding to the cs
 | ||||
|             // obtained from the current best model.
 | ||||
|             // 
 | ||||
| 
 | ||||
|             exprs cs; | ||||
|             get_current_correction_set(mdl.get(), cs); | ||||
|             unsigned max_core = max_core_size(cores); | ||||
|             if (!cs.empty() && cs.size() < max_core) { | ||||
|                 process_sat(cs);                         | ||||
|             } | ||||
|             else { | ||||
|                 process_unsat(cores);                 | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         m_lower = m_upper; | ||||
|         trace_bounds("maxres"); | ||||
|         return l_true; | ||||
|     } | ||||
| 
 | ||||
| 
 | ||||
|     lbool check_sat_hill_climb(expr_ref_vector& asms1) { | ||||
|         expr_ref_vector asms(asms1); | ||||
|         lbool is_sat = l_true; | ||||
|  | @ -399,16 +298,19 @@ public: | |||
|     virtual lbool operator()() { | ||||
|         m_defs.reset(); | ||||
|         switch(m_st) { | ||||
|         case s_mus: | ||||
|         case s_primal: | ||||
|             return mus_solver(); | ||||
|         case s_mus_mss: | ||||
|             return mus_mss_solver(); | ||||
|         case s_mss: | ||||
|             return mss_solver(); | ||||
|         case s_primal_dual: | ||||
|             return primal_dual_solver(); | ||||
|         } | ||||
|         return l_undef; | ||||
|     } | ||||
| 
 | ||||
|     virtual void collect_statistics(statistics& st) const {  | ||||
|         st.update("maxres-cores", m_stats.m_num_cores); | ||||
|         st.update("maxres-correction-sets", m_stats.m_num_cs); | ||||
|     } | ||||
| 
 | ||||
|     lbool get_cores(vector<exprs>& cores) { | ||||
|         // assume m_s is unsat.
 | ||||
|         lbool is_sat = l_false; | ||||
|  | @ -422,12 +324,14 @@ public: | |||
|             model_ref mdl; | ||||
|             get_mus_model(mdl); | ||||
|             is_sat = minimize_core(core); | ||||
|             ++m_stats.m_num_cores; | ||||
|             if (is_sat != l_true) { | ||||
|                 break; | ||||
|             } | ||||
|             if (core.empty()) { | ||||
|                 cores.reset(); | ||||
|                 return l_false; | ||||
|                 m_lower = m_upper; | ||||
|                 return l_true; | ||||
|             } | ||||
|             cores.push_back(core); | ||||
|             if (core.size() >= m_max_core_size) { | ||||
|  | @ -442,22 +346,30 @@ public: | |||
|         TRACE("opt",  | ||||
|               tout << "num cores: " << cores.size() << "\n"; | ||||
|               for (unsigned i = 0; i < cores.size(); ++i) { | ||||
|                   display_vec(tout, cores[i].size(), cores[i].c_ptr()); | ||||
|                   display_vec(tout, cores[i]); | ||||
|               } | ||||
|               tout << "num satisfying: " << asms.size() << "\n";); | ||||
|          | ||||
|         return is_sat; | ||||
|     } | ||||
| 
 | ||||
|     void get_current_correction_set(exprs& cs) { | ||||
|         model_ref mdl; | ||||
|         s().get_model(mdl); | ||||
|         update_assignment(mdl.get()); | ||||
|         get_current_correction_set(mdl.get(), cs); | ||||
|     } | ||||
| 
 | ||||
|     void get_current_correction_set(model* mdl, exprs& cs) { | ||||
|         ++m_stats.m_num_cs; | ||||
|         cs.reset(); | ||||
|         if (!mdl) return; | ||||
|         for (unsigned i = 0; i < m_asms.size(); ++i) { | ||||
|             if (!is_true(mdl, m_asms[i].get())) { | ||||
|             if (is_false(mdl, m_asms[i].get())) { | ||||
|                 cs.push_back(m_asms[i].get()); | ||||
|             } | ||||
|         } | ||||
|         TRACE("opt", display_vec(tout << "new correction set: ", cs.size(), cs.c_ptr());); | ||||
|         TRACE("opt", display_vec(tout << "new correction set: ", cs);); | ||||
|     } | ||||
| 
 | ||||
|     struct compare_asm { | ||||
|  | @ -492,7 +404,7 @@ public: | |||
| 
 | ||||
|     void process_sat(exprs const& corr_set) { | ||||
|         expr_ref fml(m), tmp(m); | ||||
|         TRACE("opt", display_vec(tout << "corr_set: ", corr_set.size(), corr_set.c_ptr());); | ||||
|         TRACE("opt", display_vec(tout << "corr_set: ", corr_set);); | ||||
|         remove_core(corr_set); | ||||
|         rational w = split_core(corr_set); | ||||
|         cs_max_resolve(corr_set, w);        | ||||
|  | @ -533,7 +445,7 @@ public: | |||
|         remove_core(core); | ||||
|         SASSERT(!core.empty()); | ||||
|         rational w = split_core(core); | ||||
|         TRACE("opt", display_vec(tout << "minimized core: ", core.size(), core.c_ptr());); | ||||
|         TRACE("opt", display_vec(tout << "minimized core: ", core);); | ||||
|         max_resolve(core, w); | ||||
|         fml = mk_not(m, mk_and(m, m_B.size(), m_B.c_ptr())); | ||||
|         s().assert_expr(fml); | ||||
|  | @ -558,22 +470,6 @@ public: | |||
|         return 0 != mdl.get(); | ||||
|     } | ||||
| 
 | ||||
|     void get_mss_model() { | ||||
|         model_ref mdl; | ||||
|         m_mss.get_model(mdl); // last model is best way to reduce search space.
 | ||||
|         update_assignment(mdl.get()); | ||||
|     } | ||||
| 
 | ||||
|     lbool get_mss(model* mdl, vector<exprs> const& cores, exprs& literals, exprs& mcs) { | ||||
|         literals.reset(); | ||||
|         mcs.reset(); | ||||
|         literals.append(m_asms.size(), m_asms.c_ptr()); | ||||
|         set_mus(false); | ||||
|         lbool is_sat = m_mss(mdl, cores, literals, mcs); | ||||
|         set_mus(true); | ||||
|         return is_sat; | ||||
|     } | ||||
| 
 | ||||
|     lbool minimize_core(exprs& core) { | ||||
|         if (m_c.sat_enabled() || core.empty()) { | ||||
|             return l_true; | ||||
|  | @ -623,11 +519,18 @@ public: | |||
|                 new_assumption(core[i], w3); | ||||
|             } | ||||
|         }         | ||||
|          | ||||
|         return w; | ||||
|     } | ||||
| 
 | ||||
|     void display_vec(std::ostream& out, unsigned sz, expr* const* args) { | ||||
|     void display_vec(std::ostream& out, exprs const& exprs) { | ||||
|         display_vec(out, exprs.size(), exprs.c_ptr()); | ||||
|     } | ||||
| 
 | ||||
|     void display_vec(std::ostream& out, expr_ref_vector const& exprs) { | ||||
|         display_vec(out, exprs.size(), exprs.c_ptr()); | ||||
|     } | ||||
| 
 | ||||
|     void display_vec(std::ostream& out, unsigned sz, expr* const* args) const { | ||||
|         for (unsigned i = 0; i < sz; ++i) { | ||||
|             out << mk_pp(args[i], m) << " : " << get_weight(args[i]) << " "; | ||||
|         } | ||||
|  | @ -691,7 +594,7 @@ public: | |||
|     // cs is a correction set (a complement of a (maximal) satisfying assignment).
 | ||||
|     void cs_max_resolve(exprs const& cs, rational const& w) { | ||||
|         if (cs.empty()) return; | ||||
|         TRACE("opt", display_vec(tout << "correction set: ", cs.size(), cs.c_ptr());); | ||||
|         TRACE("opt", display_vec(tout << "correction set: ", cs);); | ||||
|         expr_ref fml(m), asum(m); | ||||
|         app_ref cls(m), d(m), dd(m); | ||||
|         m_B.reset(); | ||||
|  | @ -733,74 +636,6 @@ public: | |||
|         s().assert_expr(fml); | ||||
|     } | ||||
| 
 | ||||
|     lbool try_improve_bound(vector<exprs>& cores, exprs& mcs) { | ||||
|         cores.reset(); | ||||
|         mcs.reset(); | ||||
|         exprs core; | ||||
|         expr_ref_vector asms(m_asms); | ||||
|         while (true) { | ||||
|             rational upper = m_max_upper; | ||||
|             unsigned sz = 0; | ||||
|             for (unsigned i = 0; m_upper <= rational(2)*upper && i < asms.size(); ++i, ++sz) { | ||||
|                 upper -= get_weight(asms[i].get()); | ||||
|             } | ||||
|             lbool is_sat = s().check_sat(sz, asms.c_ptr()); | ||||
|             switch (is_sat) { | ||||
|             case l_true: { | ||||
|                 model_ref mdl; | ||||
|                 s().get_model(mdl); // last model is best way to reduce search space.
 | ||||
|                 update_assignment(mdl.get()); | ||||
|                 exprs mss; | ||||
|                 mss.append(asms.size(), asms.c_ptr()); | ||||
|                 set_mus(false); | ||||
|                 is_sat = m_mss(m_model.get(), cores, mss, mcs); | ||||
|                 set_mus(true); | ||||
|                 if (is_sat != l_true) { | ||||
|                     return is_sat; | ||||
|                 } | ||||
|                 get_mss_model(); | ||||
|                 if (!cores.empty() && mcs.size() > cores.back().size()) { | ||||
|                     mcs.reset(); | ||||
|                 } | ||||
|                 else { | ||||
|                     cores.reset(); | ||||
|                 } | ||||
|                 return l_true; | ||||
|             } | ||||
|             case l_undef: | ||||
|                 return l_undef; | ||||
|             case l_false: | ||||
|                 core.reset(); | ||||
|                 s().get_unsat_core(core); | ||||
|                 DEBUG_CODE(verify_core(core);); | ||||
|                 is_sat = minimize_core(core); | ||||
|                 if (is_sat != l_true) { | ||||
|                     break; | ||||
|                 } | ||||
|                 if (core.empty()) { | ||||
|                     cores.reset(); | ||||
|                     mcs.reset(); | ||||
|                     return l_false; | ||||
|                 } | ||||
|                 cores.push_back(core); | ||||
|                 if (core.size() >= 3) { | ||||
|                     return l_true; | ||||
|                 } | ||||
|                 //
 | ||||
|                 // check arithmetic: cannot improve upper bound
 | ||||
|                 //
 | ||||
|                 if (m_upper <= upper) { | ||||
|                     return l_true; | ||||
|                 } | ||||
|                  | ||||
|                 remove_soft(core, asms); | ||||
|                 break; | ||||
|             } | ||||
|         } | ||||
|          | ||||
|         return l_undef; | ||||
|     } | ||||
| 
 | ||||
|     void update_assignment(model* mdl) { | ||||
|         rational upper(0); | ||||
|         expr_ref tmp(m); | ||||
|  | @ -842,6 +677,12 @@ public: | |||
|         return m.is_true(tmp); | ||||
|     } | ||||
| 
 | ||||
|     bool is_false(model* mdl, expr* e) { | ||||
|         expr_ref tmp(m); | ||||
|         VERIFY(mdl->eval(e, tmp)); | ||||
|         return m.is_false(tmp); | ||||
|     } | ||||
| 
 | ||||
|     bool is_true(expr* e) { | ||||
|         return is_true(m_model.get(), e); | ||||
|     } | ||||
|  | @ -948,16 +789,11 @@ public: | |||
| 
 | ||||
| opt::maxsmt_solver_base* opt::mk_maxres( | ||||
|     context& c, weights_t& ws, expr_ref_vector const& soft) { | ||||
|     return alloc(maxres, c, ws, soft, maxres::s_mus); | ||||
|     return alloc(maxres, c, ws, soft, maxres::s_primal); | ||||
| } | ||||
| 
 | ||||
| opt::maxsmt_solver_base* opt::mk_mus_mss_maxres( | ||||
| opt::maxsmt_solver_base* opt::mk_primal_dual_maxres( | ||||
|     context& c, weights_t& ws, expr_ref_vector const& soft) { | ||||
|     return alloc(maxres, c, ws, soft, maxres::s_mus_mss); | ||||
| } | ||||
| 
 | ||||
| opt::maxsmt_solver_base* opt::mk_mss_maxres( | ||||
|     context& c, weights_t& ws, expr_ref_vector const& soft) { | ||||
|     return alloc(maxres, c, ws, soft, maxres::s_mss); | ||||
|     return alloc(maxres, c, ws, soft, maxres::s_primal_dual); | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -24,9 +24,7 @@ namespace opt { | |||
| 
 | ||||
|     maxsmt_solver_base* mk_maxres(context& c, weights_t & ws, expr_ref_vector const& soft); | ||||
| 
 | ||||
|     maxsmt_solver_base* mk_mus_mss_maxres(context& c, weights_t & ws, expr_ref_vector const& soft); | ||||
| 
 | ||||
|     maxsmt_solver_base* mk_mss_maxres(context& c, weights_t & ws, expr_ref_vector const& soft); | ||||
|     maxsmt_solver_base* mk_primal_dual_maxres(context& c, weights_t & ws, expr_ref_vector const& soft); | ||||
| 
 | ||||
| }; | ||||
| 
 | ||||
|  |  | |||
|  | @ -106,7 +106,7 @@ namespace opt { | |||
|     } | ||||
| 
 | ||||
|     void maxsmt_solver_base::set_soft_assumptions() { | ||||
|         m_c.set_soft_assumptions() | ||||
|         m_c.set_soft_assumptions(); | ||||
|     } | ||||
| 
 | ||||
|     app* maxsmt_solver_base::mk_fresh_bool(char const* name) { | ||||
|  | @ -174,11 +174,8 @@ namespace opt { | |||
|         else if (maxsat_engine == symbol("maxres")) {             | ||||
|             m_msolver = mk_maxres(m_c, m_weights, m_soft_constraints); | ||||
|         } | ||||
|         else if (maxsat_engine == symbol("mus-mss-maxres")) {             | ||||
|             m_msolver = mk_mus_mss_maxres(m_c, m_weights, m_soft_constraints); | ||||
|         } | ||||
|         else if (maxsat_engine == symbol("mss-maxres")) {             | ||||
|             m_msolver = mk_mss_maxres(m_c, m_weights, m_soft_constraints); | ||||
|         else if (maxsat_engine == symbol("pd-maxres")) {             | ||||
|             m_msolver = mk_primal_dual_maxres(m_c, m_weights, m_soft_constraints); | ||||
|         } | ||||
|         else if (maxsat_engine == symbol("bcd2")) { | ||||
|             m_msolver = mk_bcd2(m_c, m_weights, m_soft_constraints); | ||||
|  |  | |||
|  | @ -474,8 +474,7 @@ namespace opt { | |||
|             return; | ||||
|         } | ||||
|         if (m_maxsat_engine != symbol("maxres") && | ||||
|             m_maxsat_engine != symbol("mus-mss-maxres") && | ||||
|             m_maxsat_engine != symbol("mss-maxres") && | ||||
|             m_maxsat_engine != symbol("pd-maxres") && | ||||
|             m_maxsat_engine != symbol("bcd2") && | ||||
|             m_maxsat_engine != symbol("sls")) { | ||||
|             return; | ||||
|  |  | |||
|  | @ -3,7 +3,7 @@ def_module_params('opt', | |||
|                   export=True, | ||||
|                   params=(('timeout', UINT, UINT_MAX, 'set timeout'), | ||||
|                           ('optsmt_engine', SYMBOL, 'basic', "select optimization engine: 'basic', 'farkas', 'symba'"), | ||||
| 	                  ('maxsat_engine', SYMBOL, 'wmax', "select engine for maxsat: 'fu_malik', 'core_maxsat', 'wmax', 'pbmax', 'maxres', 'bcd2', 'wpm2', 'sls', 'maxhs'"), | ||||
| 	                  ('maxsat_engine', SYMBOL, 'wmax', "select engine for maxsat: 'fu_malik', 'core_maxsat', 'wmax', 'pbmax', 'maxres', 'pd-maxres', 'bcd2', 'wpm2', 'sls', 'maxhs'"), | ||||
|                           ('priority', SYMBOL, 'lex', "select how to priortize objectives: 'lex' (lexicographic), 'pareto', or 'box'"), | ||||
|                           ('dump_benchmarks', BOOL, False, 'dump benchmarks for profiling'), | ||||
|                           ('print_model', BOOL, False, 'display model for satisfiable constraints'), | ||||
|  |  | |||
|  | @ -922,7 +922,7 @@ namespace sat { | |||
|             SASSERT(is_external((lit).var()));   | ||||
|             m_assumption_set.insert(lit);        | ||||
| 
 | ||||
|             if (m_config.soft_assumptions) { | ||||
|             if (m_config.m_soft_assumptions) { | ||||
|                 if (value(lit) == l_undef) { | ||||
|                     m_assumptions.push_back(lit);        | ||||
|                     assign(lit, justification()); | ||||
|  |  | |||
|  | @ -77,7 +77,7 @@ static void display_statistics( | |||
| 
 | ||||
|         out << "--------------\n"; | ||||
|         out << "instructions  \n"; | ||||
|         code.display(*ctx.get_rel_context(), out); | ||||
|         code.display(ex_ctx, out); | ||||
| 
 | ||||
|         out << "--------------\n"; | ||||
|         out << "big relations \n"; | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue