3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-03 12:51:22 +00:00

fixes #186, remove ite-lifting from opt_context to detect weighted maxsat

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2015-08-06 11:52:59 +02:00
parent e59ec5fefd
commit f96c0b6963
8 changed files with 109 additions and 22 deletions

View file

@ -2038,11 +2038,13 @@ app * ast_manager::mk_app_core(func_decl * decl, unsigned num_args, expr * const
} }
} }
} }
check_args(decl, num_args, new_args.c_ptr());
SASSERT(new_args.size() == num_args); SASSERT(new_args.size() == num_args);
new_node = new (mem) app(decl, num_args, new_args.c_ptr()); new_node = new (mem) app(decl, num_args, new_args.c_ptr());
r = register_node(new_node); r = register_node(new_node);
} }
else { else {
check_args(decl, num_args, args);
new_node = new (mem) app(decl, num_args, args); new_node = new (mem) app(decl, num_args, args);
r = register_node(new_node); r = register_node(new_node);
} }
@ -2064,6 +2066,22 @@ app * ast_manager::mk_app_core(func_decl * decl, unsigned num_args, expr * const
return r; return r;
} }
void ast_manager::check_args(func_decl* f, unsigned n, expr* const* es) {
for (unsigned i = 0; i < n; i++) {
sort * actual_sort = get_sort(es[i]);
sort * expected_sort = f->is_associative() ? f->get_domain(0) : f->get_domain(i);
if (expected_sort != actual_sort) {
std::ostringstream buffer;
buffer << "Sort mismatch at argument #" << (i+1)
<< " for function " << mk_pp(f,*this)
<< " supplied sort is "
<< mk_pp(actual_sort, *this);
throw ast_exception(buffer.str().c_str());
}
}
}
inline app * ast_manager::mk_app_core(func_decl * decl, expr * arg1, expr * arg2) { inline app * ast_manager::mk_app_core(func_decl * decl, expr * arg1, expr * arg2) {
expr * args[2] = { arg1, arg2 }; expr * args[2] = { arg1, arg2 };
return mk_app_core(decl, 2, args); return mk_app_core(decl, 2, args);

View file

@ -1460,6 +1460,9 @@ protected:
bool coercion_needed(func_decl * decl, unsigned num_args, expr * const * args); bool coercion_needed(func_decl * decl, unsigned num_args, expr * const * args);
void check_args(func_decl* f, unsigned n, expr* const* es);
public: public:
ast_manager(proof_gen_mode = PGM_DISABLED, char const * trace_file = 0, bool is_format_manager = false); ast_manager(proof_gen_mode = PGM_DISABLED, char const * trace_file = 0, bool is_format_manager = false);
ast_manager(proof_gen_mode, std::fstream * trace_stream, bool is_format_manager = false); ast_manager(proof_gen_mode, std::fstream * trace_stream, bool is_format_manager = false);

View file

@ -280,3 +280,9 @@ bool pb_util::has_unit_coefficients(func_decl* f) const {
} }
return true; return true;
} }
app* pb_util::mk_fresh_bool() {
symbol name = m.mk_fresh_var_name("pb");
func_decl_info info(m_fid, OP_PB_AUX_BOOL, 0, 0);
return m.mk_const(m.mk_func_decl(name, 0, (sort *const*)0, m.mk_bool_sort(), info));
}

View file

@ -35,6 +35,7 @@ enum pb_op_kind {
OP_PB_LE, // pseudo-Boolean <= (generalizes at_most_k) OP_PB_LE, // pseudo-Boolean <= (generalizes at_most_k)
OP_PB_GE, // pseudo-Boolean >= OP_PB_GE, // pseudo-Boolean >=
OP_PB_EQ, // equality OP_PB_EQ, // equality
OP_PB_AUX_BOOL, // auxiliary internal Boolean variable.
LAST_PB_OP LAST_PB_OP
}; };
@ -71,6 +72,7 @@ public:
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters, virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
unsigned arity, sort * const * domain, sort * range); unsigned arity, sort * const * domain, sort * range);
virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic); virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
}; };
@ -101,6 +103,7 @@ public:
bool is_ge(func_decl* a) const; bool is_ge(func_decl* a) const;
bool is_ge(expr* a) const { return is_app(a) && is_ge(to_app(a)->get_decl()); } bool is_ge(expr* a) const { return is_app(a) && is_ge(to_app(a)->get_decl()); }
bool is_ge(expr* a, rational& k) const; bool is_ge(expr* a, rational& k) const;
bool is_aux_bool(expr* e) const { return is_app_of(e, m_fid, OP_PB_AUX_BOOL); }
rational get_coeff(expr* a, unsigned index) const { return get_coeff(to_app(a)->get_decl(), index); } rational get_coeff(expr* a, unsigned index) const { return get_coeff(to_app(a)->get_decl(), index); }
rational get_coeff(func_decl* a, unsigned index) const; rational get_coeff(func_decl* a, unsigned index) const;
bool has_unit_coefficients(func_decl* f) const; bool has_unit_coefficients(func_decl* f) const;
@ -111,6 +114,8 @@ public:
bool is_eq(expr* e) const { return is_app(e) && is_eq(to_app(e)->get_decl()); } bool is_eq(expr* e) const { return is_app(e) && is_eq(to_app(e)->get_decl()); }
bool is_eq(expr* e, rational& k) const; bool is_eq(expr* e, rational& k) const;
app* mk_fresh_bool();
private: private:
rational to_rational(parameter const& p) const; rational to_rational(parameter const& p) const;

View file

@ -31,7 +31,6 @@ Notes:
#include "propagate_values_tactic.h" #include "propagate_values_tactic.h"
#include "solve_eqs_tactic.h" #include "solve_eqs_tactic.h"
#include "elim_uncnstr_tactic.h" #include "elim_uncnstr_tactic.h"
#include "elim_term_ite_tactic.h"
#include "tactical.h" #include "tactical.h"
#include "model_smt2_pp.h" #include "model_smt2_pp.h"
#include "card2bv_tactic.h" #include "card2bv_tactic.h"
@ -652,7 +651,6 @@ namespace opt {
and_then(mk_simplify_tactic(m), and_then(mk_simplify_tactic(m),
mk_propagate_values_tactic(m), mk_propagate_values_tactic(m),
mk_solve_eqs_tactic(m), mk_solve_eqs_tactic(m),
mk_elim_term_ite_tactic(m),
// NB: mk_elim_uncstr_tactic(m) is not sound with soft constraints // NB: mk_elim_uncstr_tactic(m) is not sound with soft constraints
mk_simplify_tactic(m)); mk_simplify_tactic(m));
opt_params optp(m_params); opt_params optp(m_params);
@ -660,14 +658,16 @@ namespace opt {
if (optp.elim_01()) { if (optp.elim_01()) {
tac2 = mk_elim01_tactic(m); tac2 = mk_elim01_tactic(m);
tac3 = mk_lia2card_tactic(m); tac3 = mk_lia2card_tactic(m);
tac4 = mk_elim_term_ite_tactic(m);
params_ref lia_p; params_ref lia_p;
lia_p.set_bool("compile_equality", optp.pb_compile_equality()); lia_p.set_bool("compile_equality", optp.pb_compile_equality());
tac3->updt_params(lia_p); tac3->updt_params(lia_p);
set_simplify(and_then(tac0.get(), tac2.get(), tac3.get(), tac4.get())); set_simplify(and_then(tac0.get(), tac2.get(), tac3.get(), mk_simplify_tactic(m)));
} }
else { else {
set_simplify(tac0.get()); tactic_ref tac1 =
and_then(tac0.get(),
mk_simplify_tactic(m));
set_simplify(tac1.get());
} }
proof_converter_ref pc; proof_converter_ref pc;
expr_dependency_ref core(m); expr_dependency_ref core(m);
@ -875,9 +875,11 @@ namespace opt {
TRACE("opt", tout << "maxsat: " << id << " offset:" << offset << "\n";); TRACE("opt", tout << "maxsat: " << id << " offset:" << offset << "\n";);
} }
else if (is_maximize(fml, tr, orig_term, index)) { else if (is_maximize(fml, tr, orig_term, index)) {
purify(tr);
m_objectives[index].m_term = tr; m_objectives[index].m_term = tr;
} }
else if (is_minimize(fml, tr, orig_term, index)) { else if (is_minimize(fml, tr, orig_term, index)) {
purify(tr);
m_objectives[index].m_term = tr; m_objectives[index].m_term = tr;
m_objectives[index].m_adjust_value.set_negate(true); m_objectives[index].m_adjust_value.set_negate(true);
} }
@ -887,6 +889,50 @@ namespace opt {
} }
} }
void context::purify(app_ref& term) {
filter_model_converter_ref fm;
if (m_arith.is_add(term)) {
expr_ref_vector args(m);
unsigned sz = term->get_num_args();
for (unsigned i = 0; i < sz; ++i) {
expr* arg = term->get_arg(i);
if (is_mul_const(arg)) {
args.push_back(arg);
}
else {
args.push_back(purify(fm, arg));
}
}
term = m_arith.mk_add(args.size(), args.c_ptr());
}
else if (m_arith.is_arith_expr(term) && !is_mul_const(term)) {
TRACE("opt", tout << "Purifying " << term << "\n";);
term = purify(fm, term);
}
if (fm) {
m_model_converter = concat(m_model_converter.get(), fm.get());
}
}
bool context::is_mul_const(expr* e) {
expr* e1, *e2;
return
is_uninterp_const(e) ||
m_arith.is_numeral(e) ||
(m_arith.is_mul(e, e1, e2) && m_arith.is_numeral(e1) && is_uninterp_const(e2)) ||
(m_arith.is_mul(e, e2, e1) && m_arith.is_numeral(e1) && is_uninterp_const(e2));
}
app* context::purify(filter_model_converter_ref& fm, expr* term) {
std::ostringstream out;
out << mk_pp(term, m);
app* q = m.mk_fresh_const(out.str().c_str(), m.get_sort(term));
if (!fm) fm = alloc(filter_model_converter, m);
m_hard_constraints.push_back(m.mk_eq(q, term));
fm->insert(q->get_decl());
return q;
}
/** /**
To select the proper theory solver we have to ensure that all theory To select the proper theory solver we have to ensure that all theory
symbols from soft constraints are reflected in the hard constraints. symbols from soft constraints are reflected in the hard constraints.
@ -894,7 +940,7 @@ namespace opt {
- filter "obj" from generated model. - filter "obj" from generated model.
*/ */
void context::mk_atomic(expr_ref_vector& terms) { void context::mk_atomic(expr_ref_vector& terms) {
ref<filter_model_converter> fm; filter_model_converter_ref fm;
for (unsigned i = 0; i < terms.size(); ++i) { for (unsigned i = 0; i < terms.size(); ++i) {
expr_ref p(terms[i].get(), m); expr_ref p(terms[i].get(), m);
app_ref q(m); app_ref q(m);
@ -902,11 +948,7 @@ namespace opt {
terms[i] = p; terms[i] = p;
} }
else { else {
q = m.mk_fresh_const("obj", m.mk_bool_sort()); terms[i] = purify(fm, p);
terms[i] = q;
m_hard_constraints.push_back(m.mk_iff(p, q));
if (!fm) fm = alloc(filter_model_converter, m);
fm->insert(q->get_decl());
} }
} }
if (fm) { if (fm) {

View file

@ -244,6 +244,9 @@ namespace opt {
bool is_maxsat(expr* fml, expr_ref_vector& terms, bool is_maxsat(expr* fml, expr_ref_vector& terms,
vector<rational>& weights, rational& offset, bool& neg, vector<rational>& weights, rational& offset, bool& neg,
symbol& id, unsigned& index); symbol& id, unsigned& index);
void purify(app_ref& term);
app* purify(filter_model_converter_ref& fm, expr* e);
bool is_mul_const(expr* e);
expr* mk_maximize(unsigned index, app* t); expr* mk_maximize(unsigned index, app* t);
expr* mk_minimize(unsigned index, app* t); expr* mk_minimize(unsigned index, app* t);
expr* mk_maxsat(unsigned index, unsigned num_fmls, expr* const* fmls); expr* mk_maxsat(unsigned index, unsigned num_fmls, expr* const* fmls);

View file

@ -410,18 +410,24 @@ namespace smt {
} }
bool theory_pb::internalize_atom(app * atom, bool gate_ctx) { bool theory_pb::internalize_atom(app * atom, bool gate_ctx) {
SASSERT(m_util.is_at_most_k(atom) || m_util.is_le(atom) ||
m_util.is_ge(atom) || m_util.is_at_least_k(atom) ||
m_util.is_eq(atom));
context& ctx = get_context(); context& ctx = get_context();
if (ctx.b_internalized(atom)) { if (ctx.b_internalized(atom)) {
return false; return false;
} }
SASSERT(!ctx.b_internalized(atom)); SASSERT(!ctx.b_internalized(atom));
m_stats.m_num_predicates++; m_stats.m_num_predicates++;
if (m_util.is_aux_bool(atom)) {
bool_var abv = ctx.mk_bool_var(atom);
ctx.set_var_theory(abv, get_id());
return true;
}
SASSERT(m_util.is_at_most_k(atom) || m_util.is_le(atom) ||
m_util.is_ge(atom) || m_util.is_at_least_k(atom) ||
m_util.is_eq(atom));
unsigned num_args = atom->get_num_args(); unsigned num_args = atom->get_num_args();
bool_var abv = ctx.mk_bool_var(atom); bool_var abv = ctx.mk_bool_var(atom);
ctx.set_var_theory(abv, get_id()); ctx.set_var_theory(abv, get_id());
@ -617,15 +623,15 @@ namespace smt {
// function internalize, where enodes for each argument // function internalize, where enodes for each argument
// is available. // is available.
if (!has_bv) { if (!has_bv) {
expr_ref tmp(m), fml(m); app_ref tmp(m), fml(m);
tmp = m.mk_fresh_const("pb_proxy",m.mk_bool_sort()); pb_util pb(m);
tmp = pb.mk_fresh_bool();
fml = m.mk_iff(tmp, arg); fml = m.mk_iff(tmp, arg);
TRACE("pb", tout << "create proxy " << fml << "\n";); TRACE("pb", tout << "create proxy " << fml << "\n";);
ctx.internalize(fml, false); ctx.internalize(fml, false);
SASSERT(ctx.b_internalized(tmp)); SASSERT(ctx.b_internalized(tmp));
bv = ctx.get_bool_var(tmp); bv = ctx.get_bool_var(tmp);
SASSERT(null_theory_var == ctx.get_var_theory(bv)); SASSERT(get_id() == ctx.get_var_theory(bv));
ctx.set_var_theory(bv, get_id());
literal lit(ctx.get_bool_var(fml)); literal lit(ctx.get_bool_var(fml));
ctx.mk_th_axiom(get_id(), 1, &lit); ctx.mk_th_axiom(get_id(), 1, &lit);
ctx.mark_as_relevant(tmp.get()); ctx.mark_as_relevant(tmp.get());
@ -1148,17 +1154,19 @@ namespace smt {
context& ctx; context& ctx;
ast_manager& m; ast_manager& m;
theory_pb& th; theory_pb& th;
pb_util pb;
typedef smt::literal literal; typedef smt::literal literal;
typedef smt::literal_vector literal_vector; typedef smt::literal_vector literal_vector;
psort_expr(context& c, theory_pb& th): psort_expr(context& c, theory_pb& th):
ctx(c), ctx(c),
m(c.get_manager()), m(c.get_manager()),
th(th) {} th(th),
pb(m) {}
literal fresh() { literal fresh() {
app_ref y(m); app_ref y(m);
y = m.mk_fresh_const("y", m.mk_bool_sort()); y = pb.mk_fresh_bool();
return literal(ctx.mk_bool_var(y)); return literal(ctx.mk_bool_var(y));
} }

View file

@ -45,4 +45,6 @@ public:
virtual model_converter * translate(ast_translation & translator); virtual model_converter * translate(ast_translation & translator);
}; };
typedef ref<filter_model_converter> filter_model_converter_ref;
#endif #endif