mirror of
https://github.com/Z3Prover/z3
synced 2025-04-08 18:31:49 +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:
parent
e59ec5fefd
commit
f96c0b6963
|
@ -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);
|
||||
new_node = new (mem) app(decl, num_args, new_args.c_ptr());
|
||||
r = register_node(new_node);
|
||||
}
|
||||
else {
|
||||
check_args(decl, num_args, args);
|
||||
new_node = new (mem) app(decl, num_args, args);
|
||||
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;
|
||||
}
|
||||
|
||||
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) {
|
||||
expr * args[2] = { arg1, arg2 };
|
||||
return mk_app_core(decl, 2, args);
|
||||
|
|
|
@ -1460,6 +1460,9 @@ protected:
|
|||
|
||||
bool coercion_needed(func_decl * decl, unsigned num_args, expr * const * args);
|
||||
|
||||
void check_args(func_decl* f, unsigned n, expr* const* es);
|
||||
|
||||
|
||||
public:
|
||||
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);
|
||||
|
|
|
@ -280,3 +280,9 @@ bool pb_util::has_unit_coefficients(func_decl* f) const {
|
|||
}
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ enum pb_op_kind {
|
|||
OP_PB_LE, // pseudo-Boolean <= (generalizes at_most_k)
|
||||
OP_PB_GE, // pseudo-Boolean >=
|
||||
OP_PB_EQ, // equality
|
||||
OP_PB_AUX_BOOL, // auxiliary internal Boolean variable.
|
||||
LAST_PB_OP
|
||||
};
|
||||
|
||||
|
@ -71,6 +72,7 @@ public:
|
|||
virtual func_decl * mk_func_decl(decl_kind k, unsigned num_parameters, parameter const * parameters,
|
||||
unsigned arity, sort * const * domain, sort * range);
|
||||
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(expr* a) const { return is_app(a) && is_ge(to_app(a)->get_decl()); }
|
||||
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(func_decl* a, unsigned index) 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, rational& k) const;
|
||||
|
||||
app* mk_fresh_bool();
|
||||
|
||||
|
||||
private:
|
||||
rational to_rational(parameter const& p) const;
|
||||
|
|
|
@ -31,7 +31,6 @@ Notes:
|
|||
#include "propagate_values_tactic.h"
|
||||
#include "solve_eqs_tactic.h"
|
||||
#include "elim_uncnstr_tactic.h"
|
||||
#include "elim_term_ite_tactic.h"
|
||||
#include "tactical.h"
|
||||
#include "model_smt2_pp.h"
|
||||
#include "card2bv_tactic.h"
|
||||
|
@ -652,7 +651,6 @@ namespace opt {
|
|||
and_then(mk_simplify_tactic(m),
|
||||
mk_propagate_values_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
|
||||
mk_simplify_tactic(m));
|
||||
opt_params optp(m_params);
|
||||
|
@ -660,14 +658,16 @@ namespace opt {
|
|||
if (optp.elim_01()) {
|
||||
tac2 = mk_elim01_tactic(m);
|
||||
tac3 = mk_lia2card_tactic(m);
|
||||
tac4 = mk_elim_term_ite_tactic(m);
|
||||
params_ref lia_p;
|
||||
lia_p.set_bool("compile_equality", optp.pb_compile_equality());
|
||||
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 {
|
||||
set_simplify(tac0.get());
|
||||
tactic_ref tac1 =
|
||||
and_then(tac0.get(),
|
||||
mk_simplify_tactic(m));
|
||||
set_simplify(tac1.get());
|
||||
}
|
||||
proof_converter_ref pc;
|
||||
expr_dependency_ref core(m);
|
||||
|
@ -875,9 +875,11 @@ namespace opt {
|
|||
TRACE("opt", tout << "maxsat: " << id << " offset:" << offset << "\n";);
|
||||
}
|
||||
else if (is_maximize(fml, tr, orig_term, index)) {
|
||||
purify(tr);
|
||||
m_objectives[index].m_term = tr;
|
||||
}
|
||||
else if (is_minimize(fml, tr, orig_term, index)) {
|
||||
purify(tr);
|
||||
m_objectives[index].m_term = tr;
|
||||
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
|
||||
symbols from soft constraints are reflected in the hard constraints.
|
||||
|
@ -894,7 +940,7 @@ namespace opt {
|
|||
- filter "obj" from generated model.
|
||||
*/
|
||||
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) {
|
||||
expr_ref p(terms[i].get(), m);
|
||||
app_ref q(m);
|
||||
|
@ -902,11 +948,7 @@ namespace opt {
|
|||
terms[i] = p;
|
||||
}
|
||||
else {
|
||||
q = m.mk_fresh_const("obj", m.mk_bool_sort());
|
||||
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());
|
||||
terms[i] = purify(fm, p);
|
||||
}
|
||||
}
|
||||
if (fm) {
|
||||
|
|
|
@ -244,6 +244,9 @@ namespace opt {
|
|||
bool is_maxsat(expr* fml, expr_ref_vector& terms,
|
||||
vector<rational>& weights, rational& offset, bool& neg,
|
||||
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_minimize(unsigned index, app* t);
|
||||
expr* mk_maxsat(unsigned index, unsigned num_fmls, expr* const* fmls);
|
||||
|
|
|
@ -410,18 +410,24 @@ namespace smt {
|
|||
}
|
||||
|
||||
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();
|
||||
if (ctx.b_internalized(atom)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
SASSERT(!ctx.b_internalized(atom));
|
||||
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();
|
||||
bool_var abv = ctx.mk_bool_var(atom);
|
||||
ctx.set_var_theory(abv, get_id());
|
||||
|
@ -617,15 +623,15 @@ namespace smt {
|
|||
// function internalize, where enodes for each argument
|
||||
// is available.
|
||||
if (!has_bv) {
|
||||
expr_ref tmp(m), fml(m);
|
||||
tmp = m.mk_fresh_const("pb_proxy",m.mk_bool_sort());
|
||||
app_ref tmp(m), fml(m);
|
||||
pb_util pb(m);
|
||||
tmp = pb.mk_fresh_bool();
|
||||
fml = m.mk_iff(tmp, arg);
|
||||
TRACE("pb", tout << "create proxy " << fml << "\n";);
|
||||
ctx.internalize(fml, false);
|
||||
SASSERT(ctx.b_internalized(tmp));
|
||||
bv = ctx.get_bool_var(tmp);
|
||||
SASSERT(null_theory_var == ctx.get_var_theory(bv));
|
||||
ctx.set_var_theory(bv, get_id());
|
||||
SASSERT(get_id() == ctx.get_var_theory(bv));
|
||||
literal lit(ctx.get_bool_var(fml));
|
||||
ctx.mk_th_axiom(get_id(), 1, &lit);
|
||||
ctx.mark_as_relevant(tmp.get());
|
||||
|
@ -1148,17 +1154,19 @@ namespace smt {
|
|||
context& ctx;
|
||||
ast_manager& m;
|
||||
theory_pb& th;
|
||||
pb_util pb;
|
||||
typedef smt::literal literal;
|
||||
typedef smt::literal_vector literal_vector;
|
||||
|
||||
psort_expr(context& c, theory_pb& th):
|
||||
ctx(c),
|
||||
m(c.get_manager()),
|
||||
th(th) {}
|
||||
th(th),
|
||||
pb(m) {}
|
||||
|
||||
literal fresh() {
|
||||
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));
|
||||
}
|
||||
|
||||
|
|
|
@ -45,4 +45,6 @@ public:
|
|||
virtual model_converter * translate(ast_translation & translator);
|
||||
};
|
||||
|
||||
typedef ref<filter_model_converter> filter_model_converter_ref;
|
||||
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue