diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp index 079597fdc..993b8d68f 100644 --- a/src/cmd_context/cmd_context.cpp +++ b/src/cmd_context/cmd_context.cpp @@ -353,6 +353,17 @@ void cmd_context::set_cancel(bool f) { m().set_cancel(f); } +opt_wrapper* cmd_context::get_opt() { + return m_opt.get(); +} + +void cmd_context::set_opt(opt_wrapper* opt) { + m_opt = opt; + for (unsigned i = 0; i < m_scopes.size(); ++i) { + m_opt->push(); + } +} + void cmd_context::global_params_updated() { m_params.updt_params(); if (m_params.m_smtlib2_compliant) @@ -1161,6 +1172,7 @@ void cmd_context::reset(bool finalize) { restore_assertions(0); if (m_solver) m_solver = 0; + m_opt = 0; m_pp_env = 0; m_dt_eh = 0; if (m_manager) { @@ -1226,6 +1238,8 @@ void cmd_context::push() { s.m_assertions_lim = m_assertions.size(); if (m_solver) m_solver->push(); + if (m_opt) + m_opt->push(); } void cmd_context::push(unsigned n) { @@ -1321,6 +1335,8 @@ void cmd_context::pop(unsigned n) { if (m_solver) { m_solver->pop(n); } + if (m_opt) + m_opt->pop(n); unsigned new_lvl = lvl - n; scope & s = m_scopes[new_lvl]; restore_func_decls(s.m_func_decls_stack_lim); @@ -1338,15 +1354,35 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions TRACE("before_check_sat", dump_assertions(tout);); if (!has_manager()) init_manager(); - if (m_solver) { + unsigned timeout = m_params.m_timeout; + scoped_watch sw(*this); + lbool r; + + if (m_opt && !m_opt->empty()) { + m_check_sat_result = get_opt(); + cancel_eh eh(*get_opt()); + scoped_ctrl_c ctrlc(eh); + scoped_timer timer(timeout, &eh); + ptr_vector cnstr(m_assertions); + cnstr.append(num_assumptions, assumptions); + get_opt()->set_hard_constraints(cnstr); + try { + r = get_opt()->optimize(); + } + catch (z3_error & ex) { + throw ex; + } + catch (z3_exception & ex) { + throw cmd_exception(ex.msg()); + } + get_opt()->set_status(r); + } + else if (m_solver) { m_check_sat_result = m_solver.get(); // solver itself stores the result. m_solver->set_progress_callback(this); - unsigned timeout = m_params.m_timeout; - scoped_watch sw(*this); cancel_eh eh(*m_solver); scoped_ctrl_c ctrlc(eh); scoped_timer timer(timeout, &eh); - lbool r; try { r = m_solver->check_sat(num_assumptions, assumptions); } @@ -1357,15 +1393,17 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions throw cmd_exception(ex.msg()); } m_solver->set_status(r); - display_sat_result(r); - validate_check_sat_result(r); - if (r == l_true) - validate_model(); } else { // There is no solver installed in the command context. regular_stream() << "unknown" << std::endl; + return; } + display_sat_result(r); + validate_check_sat_result(r); + if (r == l_true) + validate_model(); + } void cmd_context::display_sat_result(lbool r) { diff --git a/src/cmd_context/cmd_context.h b/src/cmd_context/cmd_context.h index 5f24ff808..dc0bf9833 100644 --- a/src/cmd_context/cmd_context.h +++ b/src/cmd_context/cmd_context.h @@ -111,6 +111,18 @@ struct builtin_decl { builtin_decl(family_id fid, decl_kind k, builtin_decl * n = 0):m_fid(fid), m_decl(k), m_next(n) {} }; +class opt_wrapper : public check_sat_result { +public: + virtual bool empty() = 0; + virtual void push() = 0; + virtual void pop(unsigned n) = 0; + virtual void set_cancel(bool f) = 0; + virtual void reset_cancel() = 0; + virtual void cancel() = 0; + virtual lbool optimize() = 0; + virtual void set_hard_constraints(ptr_vector & hard) = 0; +}; + class cmd_context : public progress_callback, public tactic_manager, public ast_printer_context { public: enum status { @@ -187,8 +199,9 @@ protected: svector m_scopes; scoped_ptr m_solver_factory; scoped_ptr m_interpolating_solver_factory; - ref m_solver; + ref m_solver; ref m_check_sat_result; + ref m_opt; stopwatch m_watch; @@ -255,6 +268,8 @@ public: context_params & params() { return m_params; } solver_factory &get_solver_factory() { return *m_solver_factory; } solver_factory &get_interpolating_solver_factory() { return *m_interpolating_solver_factory; } + opt_wrapper* get_opt(); + void set_opt(opt_wrapper* o); void global_params_updated(); // this method should be invoked when global (and module) params are updated. bool set_logic(symbol const & s); bool has_logic() const { return m_logic != symbol::null; } diff --git a/src/opt/opt_cmds.cpp b/src/opt/opt_cmds.cpp index 7a87ac6ca..857a3c585 100644 --- a/src/opt/opt_cmds.cpp +++ b/src/opt/opt_cmds.cpp @@ -32,33 +32,22 @@ Notes: #include "opt_params.hpp" #include "model_smt2_pp.h" -class opt_context { - cmd_context& ctx; - scoped_ptr m_opt; - hashtable m_ids; - -public: - opt_context(cmd_context& ctx): ctx(ctx) {} - opt::context& operator()() { - if (!m_opt) { - m_opt = alloc(opt::context, ctx.m()); - } - return *m_opt; - } -}; - +static opt::context& get_opt(cmd_context& cmd) { + if (!cmd.get_opt()) { + cmd.set_opt(alloc(opt::context, cmd.m())); + } + return dynamic_cast(*cmd.get_opt()); +} class assert_weighted_cmd : public cmd { - opt_context& m_opt_ctx; unsigned m_idx; expr* m_formula; rational m_weight; symbol m_id; public: - assert_weighted_cmd(cmd_context& ctx, opt_context& opt_ctx): + assert_weighted_cmd(): cmd("assert-weighted"), - m_opt_ctx(opt_ctx), m_idx(0), m_formula(0), m_weight(0) @@ -115,7 +104,7 @@ public: } virtual void execute(cmd_context & ctx) { - m_opt_ctx().add_soft_constraint(m_formula, m_weight, m_id); + get_opt(ctx).add_soft_constraint(m_formula, m_weight, m_id); reset(ctx); } @@ -126,14 +115,12 @@ public: class assert_soft_cmd : public parametric_cmd { - opt_context& m_opt_ctx; unsigned m_idx; expr* m_formula; public: - assert_soft_cmd(cmd_context& ctx, opt_context& opt_ctx): + assert_soft_cmd(): parametric_cmd("assert-soft"), - m_opt_ctx(opt_ctx), m_idx(0), m_formula(0) {} @@ -188,7 +175,7 @@ public: weight = rational::one(); } symbol id = ps().get_sym(symbol("id"), symbol::null); - m_opt_ctx().add_soft_constraint(m_formula, weight, id); + get_opt(ctx).add_soft_constraint(m_formula, weight, id); reset(ctx); } @@ -199,13 +186,11 @@ public: class min_maximize_cmd : public cmd { bool m_is_max; - opt_context& m_opt_ctx; public: - min_maximize_cmd(cmd_context& ctx, opt_context& opt_ctx, bool is_max): + min_maximize_cmd(bool is_max): cmd(is_max?"maximize":"minimize"), - m_is_max(is_max), - m_opt_ctx(opt_ctx) + m_is_max(is_max) {} virtual void reset(cmd_context & ctx) { } @@ -221,7 +206,7 @@ public: if (!is_app(t)) { throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable"); } - m_opt_ctx().add_objective(to_app(t), m_is_max); + get_opt(ctx).add_objective(to_app(t), m_is_max); } virtual void failure_cleanup(cmd_context & ctx) { @@ -233,15 +218,12 @@ public: }; class optimize_cmd : public parametric_cmd { - opt_context& m_opt_ctx; public: - optimize_cmd(opt_context& opt_ctx): - parametric_cmd("optimize"), - m_opt_ctx(opt_ctx) + optimize_cmd(): + parametric_cmd("optimize") {} virtual ~optimize_cmd() { - dealloc(&m_opt_ctx); } virtual void init_pdescrs(cmd_context & ctx, param_descrs & p) { @@ -267,7 +249,7 @@ public: virtual void execute(cmd_context & ctx) { params_ref p = ctx.params().merge_default_params(ps()); - opt::context& opt = m_opt_ctx(); + opt::context& opt = get_opt(ctx); opt.updt_params(p); unsigned timeout = p.get_uint("timeout", UINT_MAX); @@ -313,7 +295,7 @@ public: void display_result(cmd_context & ctx) { params_ref p = ctx.params().merge_default_params(ps()); - opt::context& opt = m_opt_ctx(); + opt::context& opt = get_opt(ctx); opt.display_assignment(ctx.regular_stream()); opt_params optp(p); if (optp.print_model()) { @@ -336,7 +318,7 @@ private: stats.update("time", ctx.get_seconds()); stats.update("memory", static_cast(mem)/static_cast(1024*1024)); stats.update("max memory", static_cast(max_mem)/static_cast(1024*1024)); - m_opt_ctx().collect_statistics(stats); + get_opt(ctx).collect_statistics(stats); stats.display_smt2(ctx.regular_stream()); } }; @@ -344,117 +326,10 @@ private: void install_opt_cmds(cmd_context & ctx) { - opt_context* opt_ctx = alloc(opt_context, ctx); - ctx.insert(alloc(assert_weighted_cmd, ctx, *opt_ctx)); - ctx.insert(alloc(assert_soft_cmd, ctx, *opt_ctx)); - ctx.insert(alloc(min_maximize_cmd, ctx, *opt_ctx, true)); - ctx.insert(alloc(min_maximize_cmd, ctx, *opt_ctx, false)); - ctx.insert(alloc(optimize_cmd, *opt_ctx)); + ctx.insert(alloc(assert_weighted_cmd)); + ctx.insert(alloc(assert_soft_cmd)); + ctx.insert(alloc(min_maximize_cmd, true)); + ctx.insert(alloc(min_maximize_cmd, false)); + ctx.insert(alloc(optimize_cmd)); } -#if 0 - ctx.insert(alloc(execute_cmd, *opt_ctx)); - -class execute_cmd : public parametric_cmd { -protected: - expr * m_objective; - unsigned m_idx; - opt_context& m_opt_ctx; -public: - execute_cmd(opt_context& opt_ctx): - parametric_cmd("optimize"), - m_objective(0), - m_idx(0), - m_opt_ctx(opt_ctx) - {} - - virtual void init_pdescrs(cmd_context & ctx, param_descrs & p) { - insert_timeout(p); - insert_max_memory(p); - p.insert("print_statistics", CPK_BOOL, "(default: false) print statistics."); - opt::context::collect_param_descrs(p); - } - - virtual char const * get_main_descr() const { return "check sat modulo objective function";} - virtual char const * get_usage() const { return " ( )*"; } - virtual void prepare(cmd_context & ctx) { - parametric_cmd::prepare(ctx); - reset(ctx); - m_opt_ctx(); // ensure symbol table is updated. - } - virtual void failure_cleanup(cmd_context & ctx) { - reset(ctx); - } - virtual void reset(cmd_context& ctx) { - m_objective = 0; - m_idx = 0; - } - - virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { - if (m_idx == 0) return CPK_EXPR; - return parametric_cmd::next_arg_kind(ctx); - } - - virtual void set_next_arg(cmd_context & ctx, expr * arg) { - m_objective = arg; - ++m_idx; - } - - virtual void execute(cmd_context & ctx) { - params_ref p = ctx.params().merge_default_params(ps()); - opt::context& opt = m_opt_ctx(); - opt.updt_params(p); - unsigned timeout = p.get_uint("timeout", UINT_MAX); - - ptr_vector::const_iterator it = ctx.begin_assertions(); - ptr_vector::const_iterator end = ctx.end_assertions(); - for (; it != end; ++it) { - opt.add_hard_constraint(*it); - } - lbool r = l_undef; - cancel_eh eh(opt); - { - scoped_ctrl_c ctrlc(eh); - scoped_timer timer(timeout, &eh); - cmd_context::scoped_watch sw(ctx); - try { - r = opt.optimize(m_objective); - } - catch (z3_error& ex) { - ctx.regular_stream() << "(error: " << ex.msg() << "\")" << std::endl; - } - catch (z3_exception& ex) { - ctx.regular_stream() << "(error: " << ex.msg() << "\")" << std::endl; - } - } - switch(r) { - case l_true: - ctx.regular_stream() << "sat\n"; - opt.display_assignment(ctx.regular_stream()); - break; - case l_false: - ctx.regular_stream() << "unsat\n"; - break; - case l_undef: - ctx.regular_stream() << "unknown\n"; - opt.display_range_assignment(ctx.regular_stream()); - break; - } - if (p.get_bool("print_statistics", false)) { - display_statistics(ctx); - } - } -private: - - void display_statistics(cmd_context& ctx) { - statistics stats; - unsigned long long max_mem = memory::get_max_used_memory(); - unsigned long long mem = memory::get_allocation_size(); - stats.update("time", ctx.get_seconds()); - stats.update("memory", static_cast(mem)/static_cast(1024*1024)); - stats.update("max memory", static_cast(max_mem)/static_cast(1024*1024)); - m_opt_ctx().collect_statistics(stats); - stats.display_smt2(ctx.regular_stream()); - } -}; -#endif diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp index 441c0f8a0..849b88e65 100644 --- a/src/opt/opt_context.cpp +++ b/src/opt/opt_context.cpp @@ -38,7 +38,8 @@ namespace opt { context::context(ast_manager& m): m(m), - arith(m), + m_arith(m), + m_bv(m), m_hard_constraints(m), m_optsmt(m), m_objective_refs(m) @@ -55,6 +56,43 @@ namespace opt { } } + void context::push() { + m_objectives_lim.push_back(m_objectives.size()); + m_objectives_term_trail_lim.push_back(m_objectives_term_trail.size()); + m_solver->push(); + } + + void context::pop(unsigned n) { + m_solver->pop(n); + while (n > 0) { + --n; + unsigned k = m_objectives_term_trail_lim.back(); + while (m_objectives_term_trail.size() > k) { + unsigned idx = m_objectives_term_trail.back(); + m_objectives[idx].m_terms.pop_back(); + m_objectives[idx].m_weights.pop_back(); + m_objectives_term_trail.pop_back(); + } + m_objectives_term_trail_lim.pop_back(); + k = m_objectives_lim.back(); + while (m_objectives.size() > k) { + objective& obj = m_objectives.back(); + if (obj.m_type == O_MAXSMT) { + dealloc(m_maxsmts[obj.m_id]); + m_maxsmts.erase(obj.m_id); + m_indices.erase(obj.m_id); + } + m_objectives.pop_back(); + } + m_objectives_lim.pop_back(); + } + } + + void context::set_hard_constraints(ptr_vector& fmls) { + m_hard_constraints.reset(); + m_hard_constraints.append(fmls.size(), fmls.c_ptr()); + } + unsigned context::add_soft_constraint(expr* f, rational const& w, symbol const& id) { maxsmt* ms; if (w.is_neg()) { @@ -77,13 +115,14 @@ namespace opt { unsigned idx = m_indices[id]; m_objectives[idx].m_terms.push_back(f); m_objectives[idx].m_weights.push_back(w); + m_objectives_term_trail.push_back(idx); return idx; } unsigned context::add_objective(app* t, bool is_max) { app_ref tr(t, m); - if (!arith.is_arith_expr(t)) { - throw default_exception("Objective must be integer or real"); + if (!m_bv.is_bv(t) && !m_arith.is_int_real(t)) { + throw default_exception("Objective must be bit-vector, integer or real"); } unsigned index = m_objectives.size(); m_objectives.push_back(objective(is_max, tr, index)); @@ -92,6 +131,7 @@ namespace opt { lbool context::optimize() { opt_solver& s = get_solver(); + m_optsmt.reset(); normalize(); internalize(); solver::scoped_push _sp(s); @@ -225,7 +265,7 @@ namespace opt { objective const& obj = m_objectives[j]; bounds[i][j].second = bounds[j][j].second; } - display_bounds(verbose_stream() << "new bound\n", bounds[i]); + IF_VERBOSE(0, display_bounds(verbose_stream() << "new bound\n", bounds[i]);); } for (unsigned i = 0; i < bounds.size(); ++i) { @@ -247,13 +287,13 @@ namespace opt { bool at_bound = true; for (unsigned j = 0; j < b.size(); ++j) { objective const& obj = m_objectives[j]; - if (m_model->eval(obj.m_term, val) && arith.is_numeral(val, r)) { + if (m_model->eval(obj.m_term, val) && is_numeral(val, r)) { mids[j] = inf_eps(r); } at_bound = at_bound && mids[j] == b[j].second; b[j].second = mids[j]; } - display_bounds(verbose_stream() << "new bound\n", b); + IF_VERBOSE(0, display_bounds(verbose_stream() << "new bound\n", b);); if (!at_bound) { bounds.push_back(b); } @@ -266,7 +306,7 @@ namespace opt { if (j > 0) { b2[j-1].second = b[j-1].second; } - display_bounds(verbose_stream() << "refined bound\n", b2); + IF_VERBOSE(0, display_bounds(verbose_stream() << "refined bound\n", b2);); bounds.push_back(b2); } break; @@ -294,6 +334,11 @@ namespace opt { return *m_solver.get(); } + bool context::is_numeral(expr* e, rational & n) const { + unsigned sz; + return m_arith.is_numeral(e, n) || m_bv.is_numeral(e, n, sz); + } + void context::normalize() { expr_ref_vector fmls(m); to_fmls(fmls); @@ -373,8 +418,9 @@ namespace opt { app_ref term(m); expr* orig_term; offset = rational::zero(); - if (is_minimize(fml, term, orig_term, index) && - get_pb_sum(term, terms, weights, offset)) { + bool is_max = is_maximize(fml, term, orig_term, index); + bool is_min = !is_max && is_minimize(fml, term, orig_term, index); + if (is_min && get_pb_sum(term, terms, weights, offset)) { TRACE("opt", tout << "try to convert minimization" << mk_pp(term, m) << "\n";); // minimize 2*x + 3*y // <=> @@ -403,8 +449,7 @@ namespace opt { id = symbol(out.str().c_str()); return true; } - if (is_maximize(fml, term, orig_term, index) && - get_pb_sum(term, terms, weights, offset)) { + if (is_max && get_pb_sum(term, terms, weights, offset)) { TRACE("opt", tout << "try to convert maximization" << mk_pp(term, m) << "\n";); // maximize 2*x + 3*y - z // <=> @@ -427,6 +472,25 @@ namespace opt { id = symbol(out.str().c_str()); return true; } + if ((is_max || is_min) && m_bv.is_bv(term)) { + offset.reset(); + unsigned bv_size = m_bv.get_bv_size(term); + expr_ref val(m); + val = m_bv.mk_numeral(is_max, 1); + for (unsigned i = 0; i < bv_size; ++i) { + rational w = power(rational(2),i); + weights.push_back(w); + terms.push_back(m.mk_eq(val, m_bv.mk_extract(i, i, term))); + if (is_max) { + offset += w; + } + } + neg = is_max; + std::ostringstream out; + out << mk_pp(orig_term, m); + id = symbol(out.str().c_str()); + return true; + } return false; } @@ -535,7 +599,7 @@ namespace opt { switch(obj.m_type) { case O_MINIMIZE: { app_ref tmp(m); - tmp = arith.mk_uminus(obj.m_term); + tmp = m_arith.mk_uminus(obj.m_term); obj.m_index = m_optsmt.add(tmp); break; } @@ -560,12 +624,12 @@ namespace opt { objective const& obj = m_objectives[i]; switch(obj.m_type) { case O_MINIMIZE: - if (m_model->eval(obj.m_term, val) && arith.is_numeral(val, r)) { + if (m_model->eval(obj.m_term, val) && is_numeral(val, r)) { m_optsmt.update_lower(obj.m_index, -r); } break; case O_MAXIMIZE: - if (m_model->eval(obj.m_term, val) && arith.is_numeral(val, r)) { + if (m_model->eval(obj.m_term, val) && is_numeral(val, r)) { m_optsmt.update_lower(obj.m_index, r); } break; @@ -642,7 +706,6 @@ namespace opt { } } - inf_eps context::get_upper_as_num(unsigned idx) { if (idx > m_objectives.size()) { throw default_exception("index out of bounds"); @@ -679,30 +742,30 @@ namespace opt { rational eps = n.get_infinitesimal(); expr_ref_vector args(m); if (!inf.is_zero()) { - expr* oo = m.mk_const(symbol("oo"), arith.mk_int()); + expr* oo = m.mk_const(symbol("oo"), m_arith.mk_int()); if (inf.is_one()) { args.push_back(oo); } else { - args.push_back(arith.mk_mul(arith.mk_numeral(inf, inf.is_int()), oo)); + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(inf, inf.is_int()), oo)); } } if (!r.is_zero()) { - args.push_back(arith.mk_numeral(r, r.is_int())); + args.push_back(m_arith.mk_numeral(r, r.is_int())); } if (!eps.is_zero()) { - expr* ep = m.mk_const(symbol("epsilon"), arith.mk_int()); + expr* ep = m.mk_const(symbol("epsilon"), m_arith.mk_int()); if (eps.is_one()) { args.push_back(ep); } else { - args.push_back(arith.mk_mul(arith.mk_numeral(eps, eps.is_int()), ep)); + args.push_back(m_arith.mk_mul(m_arith.mk_numeral(eps, eps.is_int()), ep)); } } switch(args.size()) { - case 0: return expr_ref(arith.mk_numeral(rational(0), true), m); + case 0: return expr_ref(m_arith.mk_numeral(rational(0), true), m); case 1: return expr_ref(args[0].get(), m); - default: return expr_ref(arith.mk_add(args.size(), args.c_ptr()), m); + default: return expr_ref(m_arith.mk_add(args.size(), args.c_ptr()), m); } } @@ -870,7 +933,7 @@ namespace opt { if (n.get_infinity().is_zero() && n.get_infinitesimal().is_zero() && m_model->eval(obj.m_term, val) && - arith.is_numeral(val, r1)) { + is_numeral(val, r1)) { rational r2 = n.get_rational(); CTRACE("opt", r1 != r2, tout << obj.m_term << " evaluates to " << r1 << " but has objective " << r2 << "\n";); CTRACE("opt", r1 != r2, model_smt2_pp(tout, m, *m_model, 0);); diff --git a/src/opt/opt_context.h b/src/opt/opt_context.h index 12c9a5c5b..798a67a1c 100644 --- a/src/opt/opt_context.h +++ b/src/opt/opt_context.h @@ -32,13 +32,15 @@ Notes: #include "model_converter.h" #include "tactic.h" #include "arith_decl_plugin.h" +#include "bv_decl_plugin.h" +#include "cmd_context.h" namespace opt { class opt_solver; - class context { + class context : public opt_wrapper { struct free_func_visitor; typedef map map_t; typedef map map_id; @@ -80,7 +82,8 @@ namespace opt { {} }; ast_manager& m; - arith_util arith; + arith_util m_arith; + bv_util m_bv; expr_ref_vector m_hard_constraints; ref m_solver; params_ref m_params; @@ -88,6 +91,9 @@ namespace opt { map_t m_maxsmts; map_id m_indices; vector m_objectives; + unsigned_vector m_objectives_lim; + unsigned_vector m_objectives_term_trail; + unsigned_vector m_objectives_term_trail_lim; model_ref m_model; model_converter_ref m_model_converter; obj_map m_objective_fns; @@ -96,19 +102,26 @@ namespace opt { tactic_ref m_simplify; public: context(ast_manager& m); - ~context(); + virtual ~context(); unsigned add_soft_constraint(expr* f, rational const& w, symbol const& id); unsigned add_objective(app* t, bool is_max); void add_hard_constraint(expr* f) { m_hard_constraints.push_back(f); } - lbool optimize(); + virtual void push(); + virtual void pop(unsigned n); + virtual bool empty() { return m_objectives.empty(); } + virtual void set_cancel(bool f); + virtual void reset_cancel() { set_cancel(false); } + virtual void cancel() { set_cancel(true); } + virtual void set_hard_constraints(ptr_vector & hard); + virtual lbool optimize(); + virtual void get_model(model_ref& m); + virtual void collect_statistics(statistics& stats) const; + virtual proof* get_proof() { return 0; } + virtual void get_labels(svector & r) {} + virtual void get_unsat_core(ptr_vector & r) {} + virtual std::string reason_unknown() const { return std::string("unknown"); } - void get_model(model_ref& m); - - void set_cancel(bool f); - void reset_cancel() { set_cancel(false); } - void cancel() { set_cancel(true); } - void collect_statistics(statistics& stats) const; void display_assignment(std::ostream& out); void display_range_assignment(std::ostream& out); static void collect_param_descrs(param_descrs & r); @@ -153,6 +166,8 @@ namespace opt { opt_solver& get_solver(); + bool is_numeral(expr* e, rational& n) const; + void display_objective(std::ostream& out, objective const& obj) const; void display_bounds(std::ostream& out, bounds_t const& b) const; diff --git a/src/opt/optsmt.cpp b/src/opt/optsmt.cpp index 26f8116a0..7177c7679 100644 --- a/src/opt/optsmt.cpp +++ b/src/opt/optsmt.cpp @@ -51,7 +51,7 @@ namespace opt { void optsmt::set_cancel(bool f) { - m_cancel = true; + m_cancel = f; } void optsmt::set_max(vector& dst, vector const& src) { @@ -379,5 +379,13 @@ namespace opt { m_engine = _p.engine(); } + void optsmt::reset() { + m_lower.reset(); + m_upper.reset(); + m_objs.reset(); + m_vars.reset(); + m_model.reset(); + m_s = 0; + } } diff --git a/src/opt/optsmt.h b/src/opt/optsmt.h index ccb7de1b5..060ae9aaa 100644 --- a/src/opt/optsmt.h +++ b/src/opt/optsmt.h @@ -61,6 +61,8 @@ namespace opt { void get_model(model_ref& mdl); void update_lower(unsigned idx, rational const& r); + + void reset(); private: