mirror of
https://github.com/Z3Prover/z3
synced 2025-04-23 09:05:31 +00:00
fix performance for model construction, recognize concats of values as a value for pre-processing
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
72ec6dc8e1
commit
45fdb95f53
9 changed files with 163 additions and 244 deletions
|
@ -116,11 +116,9 @@ public:
|
|||
{}
|
||||
|
||||
virtual void reset(cmd_context & ctx) { }
|
||||
|
||||
virtual char const * get_usage() const { return "<term>"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "check sat modulo objective function";}
|
||||
virtual unsigned get_arity() const { return 1; }
|
||||
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const { return CPK_EXPR; }
|
||||
|
||||
|
@ -139,204 +137,72 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class alternate_min_max_cmd : public cmd {
|
||||
app_ref_vector m_vars;
|
||||
svector<bool> m_is_max;
|
||||
unsigned m_position;
|
||||
public:
|
||||
alternate_min_max_cmd(ast_manager& m):
|
||||
cmd("min-max"),
|
||||
m_vars(m),
|
||||
m_position(0)
|
||||
{}
|
||||
|
||||
virtual void reset(cmd_context & ctx) {
|
||||
m_vars.reset();
|
||||
m_is_max.reset();
|
||||
m_position = 0;
|
||||
}
|
||||
virtual char const * get_usage() const { return "(min | max | var)+ <term>"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "check sat modulo alternating min-max objectives";}
|
||||
virtual unsigned get_arity() const { return 2; }
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
|
||||
switch (m_position) {
|
||||
case 0: return CPK_SYMBOL_LIST;
|
||||
case 1: return CPK_EXPR;
|
||||
default: return CPK_SYMBOL;
|
||||
}
|
||||
}
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, unsigned num, symbol const * slist) {
|
||||
bool is_max = false;
|
||||
for (unsigned i = 0; i < num; ++i) {
|
||||
if (slist[i] == symbol("max")) {
|
||||
is_max = true;
|
||||
}
|
||||
else if (slist[i] == symbol("min")) {
|
||||
is_max = false;
|
||||
}
|
||||
else {
|
||||
m_is_max.push_back(is_max);
|
||||
m_vars.push_back(ctx.m().mk_const(ctx.find_func_decl(slist[i])));
|
||||
}
|
||||
}
|
||||
++m_position;
|
||||
}
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, expr * t) {
|
||||
if (!is_app(t)) {
|
||||
throw cmd_exception("malformed objective term: it cannot be a quantifier or bound variable");
|
||||
}
|
||||
++m_position;
|
||||
get_opt(ctx).min_max(to_app(t), m_vars, m_is_max);
|
||||
}
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) { }
|
||||
};
|
||||
|
||||
|
||||
void install_opt_cmds(cmd_context & ctx) {
|
||||
ctx.insert(alloc(assert_soft_cmd));
|
||||
ctx.insert(alloc(min_maximize_cmd, true));
|
||||
ctx.insert(alloc(min_maximize_cmd, false));
|
||||
ctx.insert(alloc(alternate_min_max_cmd, ctx.m()));
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
ctx.insert(alloc(optimize_cmd));
|
||||
ctx.insert(alloc(assert_weighted_cmd));
|
||||
|
||||
|
||||
class optimize_cmd : public parametric_cmd {
|
||||
public:
|
||||
optimize_cmd():
|
||||
parametric_cmd("optimize")
|
||||
{}
|
||||
|
||||
virtual ~optimize_cmd() {
|
||||
}
|
||||
|
||||
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 "(<keyword> <value>)*"; }
|
||||
virtual void prepare(cmd_context & ctx) {
|
||||
parametric_cmd::prepare(ctx);
|
||||
}
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
|
||||
return parametric_cmd::next_arg_kind(ctx);
|
||||
}
|
||||
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
params_ref p = ctx.params().merge_default_params(ps());
|
||||
opt::context& opt = get_opt(ctx);
|
||||
opt.updt_params(p);
|
||||
unsigned timeout = p.get_uint("timeout", UINT_MAX);
|
||||
|
||||
ptr_vector<expr>::const_iterator it = ctx.begin_assertions();
|
||||
ptr_vector<expr>::const_iterator end = ctx.end_assertions();
|
||||
for (; it != end; ++it) {
|
||||
opt.add_hard_constraint(*it);
|
||||
}
|
||||
lbool r = l_undef;
|
||||
cancel_eh<reslimit> eh(m.limit());
|
||||
{
|
||||
scoped_ctrl_c ctrlc(eh);
|
||||
scoped_timer timer(timeout, &eh);
|
||||
cmd_context::scoped_watch sw(ctx);
|
||||
try {
|
||||
r = opt.optimize();
|
||||
if (r == l_true && opt.is_pareto()) {
|
||||
while (r == l_true) {
|
||||
display_result(ctx);
|
||||
ctx.regular_stream() << "\n";
|
||||
r = opt.optimize();
|
||||
}
|
||||
if (p.get_bool("print_statistics", false)) {
|
||||
display_statistics(ctx);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
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";
|
||||
display_result(ctx);
|
||||
break;
|
||||
}
|
||||
case l_false:
|
||||
ctx.regular_stream() << "unsat\n";
|
||||
break;
|
||||
case l_undef:
|
||||
ctx.regular_stream() << "unknown\n";
|
||||
display_result(ctx);
|
||||
break;
|
||||
}
|
||||
if (p.get_bool("print_statistics", false)) {
|
||||
display_statistics(ctx);
|
||||
}
|
||||
}
|
||||
|
||||
void display_result(cmd_context & ctx) {
|
||||
params_ref p = ctx.params().merge_default_params(ps());
|
||||
opt::context& opt = get_opt(ctx);
|
||||
opt.display_assignment(ctx.regular_stream());
|
||||
opt_params optp(p);
|
||||
if (optp.print_model()) {
|
||||
model_ref mdl;
|
||||
opt.get_model(mdl);
|
||||
if (mdl) {
|
||||
ctx.regular_stream() << "(model " << std::endl;
|
||||
model_smt2_pp(ctx.regular_stream(), ctx, *(mdl.get()), 2);
|
||||
ctx.regular_stream() << ")" << std::endl;
|
||||
}
|
||||
}
|
||||
}
|
||||
private:
|
||||
|
||||
void display_statistics(cmd_context& ctx) {
|
||||
statistics stats;
|
||||
get_opt(ctx).collect_statistics(stats);
|
||||
stats.update("time", ctx.get_seconds());
|
||||
stats.display_smt2(ctx.regular_stream());
|
||||
}
|
||||
};
|
||||
|
||||
class assert_weighted_cmd : public cmd {
|
||||
unsigned m_idx;
|
||||
expr* m_formula;
|
||||
rational m_weight;
|
||||
symbol m_id;
|
||||
|
||||
public:
|
||||
assert_weighted_cmd():
|
||||
cmd("assert-weighted"),
|
||||
m_idx(0),
|
||||
m_formula(0),
|
||||
m_weight(0)
|
||||
{}
|
||||
|
||||
virtual ~assert_weighted_cmd() {
|
||||
}
|
||||
|
||||
virtual void reset(cmd_context & ctx) {
|
||||
m_idx = 0;
|
||||
m_formula = 0;
|
||||
m_id = symbol::null;
|
||||
}
|
||||
|
||||
virtual char const * get_usage() const { return "<formula> <rational-weight>"; }
|
||||
virtual char const * get_descr(cmd_context & ctx) const { return "assert soft constraint with weight"; }
|
||||
virtual unsigned get_arity() const { return VAR_ARITY; }
|
||||
|
||||
// command invocation
|
||||
virtual void prepare(cmd_context & ctx) {}
|
||||
virtual cmd_arg_kind next_arg_kind(cmd_context & ctx) const {
|
||||
switch(m_idx) {
|
||||
case 0: return CPK_EXPR;
|
||||
case 1: return CPK_NUMERAL;
|
||||
default: return CPK_SYMBOL;
|
||||
}
|
||||
}
|
||||
virtual void set_next_arg(cmd_context & ctx, rational const & val) {
|
||||
SASSERT(m_idx == 1);
|
||||
if (!val.is_pos()) {
|
||||
throw cmd_exception("Invalid weight. Weights must be positive.");
|
||||
}
|
||||
m_weight = val;
|
||||
++m_idx;
|
||||
}
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, expr * t) {
|
||||
SASSERT(m_idx == 0);
|
||||
if (!ctx.m().is_bool(t)) {
|
||||
throw cmd_exception("Invalid type for expression. Expected Boolean type.");
|
||||
}
|
||||
m_formula = t;
|
||||
++m_idx;
|
||||
}
|
||||
|
||||
virtual void set_next_arg(cmd_context & ctx, symbol const& s) {
|
||||
SASSERT(m_idx > 1);
|
||||
m_id = s;
|
||||
++m_idx;
|
||||
}
|
||||
|
||||
virtual void failure_cleanup(cmd_context & ctx) {
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void execute(cmd_context & ctx) {
|
||||
get_opt(ctx).add_soft_constraint(m_formula, m_weight, m_id);
|
||||
reset(ctx);
|
||||
}
|
||||
|
||||
virtual void finalize(cmd_context & ctx) {
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -193,6 +193,8 @@ namespace opt {
|
|||
return m_scoped_state.add(t, is_max);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void context::import_scoped_state() {
|
||||
m_optsmt.reset();
|
||||
reset_maxsmts();
|
||||
|
@ -209,6 +211,20 @@ namespace opt {
|
|||
m_hard_constraints.append(s.m_hard);
|
||||
}
|
||||
|
||||
lbool context::min_max(app* t, app_ref_vector const& vars, svector<bool> const& is_max) {
|
||||
clear_state();
|
||||
init_solver();
|
||||
import_scoped_state();
|
||||
normalize();
|
||||
internalize();
|
||||
update_solver();
|
||||
solver& s = get_solver();
|
||||
s.assert_expr(m_hard_constraints);
|
||||
std::cout << "min-max is TBD\n";
|
||||
return l_undef;
|
||||
}
|
||||
|
||||
|
||||
lbool context::optimize() {
|
||||
if (m_pareto) {
|
||||
return execute_pareto();
|
||||
|
@ -223,10 +239,7 @@ namespace opt {
|
|||
internalize();
|
||||
update_solver();
|
||||
solver& s = get_solver();
|
||||
for (unsigned i = 0; i < m_hard_constraints.size(); ++i) {
|
||||
TRACE("opt", tout << "Hard constraint: " << mk_ismt2_pp(m_hard_constraints[i].get(), m) << std::endl;);
|
||||
s.assert_expr(m_hard_constraints[i].get());
|
||||
}
|
||||
s.assert_expr(m_hard_constraints);
|
||||
display_benchmark();
|
||||
IF_VERBOSE(1, verbose_stream() << "(optimize:check-sat)\n";);
|
||||
lbool is_sat = s.check_sat(0,0);
|
||||
|
|
|
@ -172,6 +172,7 @@ namespace opt {
|
|||
virtual ~context();
|
||||
unsigned add_soft_constraint(expr* f, rational const& w, symbol const& id);
|
||||
unsigned add_objective(app* t, bool is_max);
|
||||
lbool min_max(app* t, app_ref_vector const& vars, svector<bool> const& is_max);
|
||||
void add_hard_constraint(expr* f);
|
||||
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue