3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-10 19:27:06 +00:00

fix sorting network bug, add network compilation,...

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-09-11 18:47:21 -07:00
parent 72f09e4729
commit 019ff77613
15 changed files with 350 additions and 100 deletions

View file

@ -2058,6 +2058,22 @@ app * ast_manager::mk_app(func_decl * decl, unsigned num_args, expr * const * ar
return r;
}
expr* ast_manager::mk_or_reduced(unsigned n, expr* const* args) {
switch (n) {
case 0: return mk_false();
case 1: return args[0];
default: return mk_or(n, args);
}
}
expr* ast_manager::mk_and_reduced(unsigned n, expr* const* args) {
switch (n) {
case 0: return mk_true();
case 1: return args[0];
default: return mk_and(n, args);
}
}
func_decl * ast_manager::mk_fresh_func_decl(symbol const & prefix, symbol const & suffix, unsigned arity,
sort * const * domain, sort * range) {
func_decl_info info(null_family_id, null_decl_kind);

View file

@ -2004,6 +2004,9 @@ public:
app * mk_true() { return m_true; }
app * mk_false() { return m_false; }
app * mk_interp(expr * arg) { return mk_app(m_basic_family_id, OP_INTERP, arg); }
expr * mk_or_reduced(unsigned num_args, expr * const * args);
expr * mk_and_reduced(unsigned num_args, expr * const * args);
func_decl* mk_and_decl() {
sort* domain[2] = { m_bool_sort, m_bool_sort };

View file

@ -271,3 +271,12 @@ rational pb_util::to_rational(parameter const& p) const {
SASSERT(p.is_rational());
return p.get_rational();
}
bool pb_util::has_unit_coefficients(func_decl* f) const {
if (is_at_most_k(f) || is_at_least_k(f)) return true;
unsigned sz = f->get_arity();
for (unsigned i = 0; i < sz; ++i) {
if (!get_coeff(f, i).is_one()) return false;
}
return true;
}

View file

@ -103,6 +103,9 @@ public:
bool is_ge(expr* a, rational& k) const;
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;
bool has_unit_coefficients(expr* f) const { return is_app(f) && has_unit_coefficients(to_app(f)->get_decl()); }
bool is_eq(func_decl* f) const;
bool is_eq(expr* e) const { return is_app(e) && is_eq(to_app(e)->get_decl()); }

View file

@ -397,8 +397,12 @@ public:
*/
sort_assumptions(asms);
unsigned index = 0;
unsigned last_index = 0;
while (index < asms.size() && is_sat != l_false) {
index = next_index(asms, index);
while (asms.size() > 10*(index - last_index) && index < asms.size()) {
index = next_index(asms, index);
}
last_index = index;
is_sat = s().check_sat(index, asms.c_ptr());
}
}

View file

@ -69,7 +69,6 @@ namespace opt {
m_objectives_lim.pop_back();
m_hard_lim.pop_back();
}
void context::scoped_state::add(expr* hard) {
m_hard.push_back(hard);
@ -608,7 +607,7 @@ namespace opt {
for (unsigned i = 0; i < a->get_num_args(); ++i) {
expr* arg = a->get_arg(i);
if (m.is_true(arg)) {
// skip
}
else if (m.is_false(arg)) {
offset += m_objectives[index].m_weights[i];
@ -764,8 +763,8 @@ namespace opt {
SASSERT(obj.m_id == id);
obj.m_terms.reset();
obj.m_terms.append(terms);
obj.m_offset = offset;
obj.m_neg = neg;
obj.m_adjust_bound.set_offset(offset);
obj.m_adjust_bound.set_negate(neg);
TRACE("opt", tout << "maxsat: " << id << " offset:" << offset << "\n";);
}
else if (is_maximize(fml, tr, orig_term, index)) {
@ -835,23 +834,23 @@ namespace opt {
switch(obj.m_type) {
case O_MINIMIZE:
if (m_model->eval(obj.m_term, val) && is_numeral(val, r)) {
r += obj.m_offset;
inf_eps val = obj.m_adjust_bound.neg_add(r);
if (is_lower) {
m_optsmt.update_lower(obj.m_index, inf_eps(-r), override);
m_optsmt.update_lower(obj.m_index, val, override);
}
else {
m_optsmt.update_upper(obj.m_index, inf_eps(-r), override);
m_optsmt.update_upper(obj.m_index, val, override);
}
}
break;
case O_MAXIMIZE:
if (m_model->eval(obj.m_term, val) && is_numeral(val, r)) {
r += obj.m_offset;
inf_eps val = obj.m_adjust_bound.neg_add(r);
if (is_lower) {
m_optsmt.update_lower(obj.m_index, inf_eps(r), override);
m_optsmt.update_lower(obj.m_index, val, override);
}
else {
m_optsmt.update_upper(obj.m_index, inf_eps(r), override);
m_optsmt.update_upper(obj.m_index, val, override);
}
}
break;
@ -921,10 +920,7 @@ namespace opt {
switch(obj.m_type) {
case O_MAXSMT: {
rational r = m_maxsmts.find(obj.m_id)->get_lower();
TRACE("opt", tout << "maxsmt: " << r << " negate: " << obj.m_neg << " offset: " << obj.m_offset << "\n";);
if (obj.m_neg) r.neg();
r += obj.m_offset;
return inf_eps(r);
return obj.m_adjust_bound.neg_add(r);
}
case O_MINIMIZE:
return -m_optsmt.get_upper(obj.m_index);
@ -942,13 +938,9 @@ namespace opt {
}
objective const& obj = m_objectives[idx];
switch(obj.m_type) {
case O_MAXSMT: {
rational r = m_maxsmts.find(obj.m_id)->get_upper();
TRACE("opt", tout << "maxsmt: " << r << " negate: " << obj.m_neg << " offset: " << obj.m_offset << "\n";);
if (obj.m_neg) r.neg();
r += obj.m_offset;
return inf_eps(r);
}
case O_MAXSMT:
return obj.m_adjust_bound.neg_add(m_maxsmts.find(obj.m_id)->get_upper());
// TBD: adjust bound
case O_MINIMIZE:
return -m_optsmt.get_lower(obj.m_index);
case O_MAXIMIZE:

View file

@ -51,8 +51,7 @@ namespace opt {
app_ref m_term; // for maximize, minimize term
expr_ref_vector m_terms; // for maxsmt
vector<rational> m_weights; // for maxsmt
rational m_offset; // for maxsmt
bool m_neg; // negate
bound_adjustment m_adjust_bound;
symbol m_id; // for maxsmt
unsigned m_index; // for maximize/minimize index
@ -60,18 +59,18 @@ namespace opt {
m_type(is_max?O_MAXIMIZE:O_MINIMIZE),
m_term(t),
m_terms(t.get_manager()),
m_offset(0),
m_neg(false),
m_id(),
m_index(idx)
{}
{
if (!is_max) {
m_adjust_bound.set_negate(true);
}
}
objective(ast_manager& m, symbol id):
m_type(O_MAXSMT),
m_term(m),
m_terms(m),
m_offset(0),
m_neg(false),
m_id(id),
m_index(0)
{}

View file

@ -36,6 +36,33 @@ namespace opt {
typedef inf_eps_rational<inf_rational> inf_eps;
// Adjust bound bound |-> (m_negate?-1:1)*(m_offset + bound)
class bound_adjustment {
rational m_offset;
bool m_negate;
public:
bound_adjustment(rational const& offset, bool neg):
m_offset(offset),
m_negate(neg)
{}
bound_adjustment(): m_offset(0), m_negate(false) {}
void set_offset(rational const& o) { m_offset = o; }
void set_negate(bool neg) { m_negate = neg; }
rational const& get_offset() const { return m_offset; }
bool get_negate() { return m_negate; }
inf_eps add_neg(rational const& r) const {
rational result = r + m_offset;
if (m_negate) result.neg();
return inf_eps(result);
}
inf_eps neg_add(rational const& r) const {
rational result = r;
if (m_negate) result.neg();
result += m_offset;
return inf_eps(result);
}
};
class opt_solver : public solver_na2as {
private:

View file

@ -958,7 +958,7 @@ namespace smt {
typename atoms::iterator lo_inf1 = begin1, lo_sup1 = begin1;
typename atoms::iterator hi_inf1 = begin2, hi_sup1 = begin2;
bool flo_inf, fhi_inf, flo_sup, fhi_sup;
//std::cout << atoms.size() << "\n";
// std::cout << atoms.size() << "\n";
ptr_addr_hashtable<typename atom> visited;
for (unsigned i = 0; i < atoms.size(); ++i) {
atom* a1 = atoms[i];
@ -966,8 +966,8 @@ namespace smt {
hi_inf1 = next_inf(a1, A_UPPER, hi_inf, end, fhi_inf);
lo_sup1 = next_sup(a1, A_LOWER, lo_sup, end, flo_sup);
hi_sup1 = next_sup(a1, A_UPPER, hi_sup, end, fhi_sup);
//std::cout << "v" << a1->get_var() << ((a1->get_atom_kind()==A_LOWER)?" <= ":" >= ") << a1->get_k() << "\n";
//std::cout << (lo_inf1 != end) << " " << (lo_sup1 != end) << " " << (hi_inf1 != end) << " " << (hi_sup1 != end) << "\n";
// std::cout << "v" << a1->get_var() << ((a1->get_atom_kind()==A_LOWER)?" <= ":" >= ") << a1->get_k() << "\n";
// std::cout << (lo_inf1 != end) << " " << (lo_sup1 != end) << " " << (hi_inf1 != end) << " " << (hi_sup1 != end) << "\n";
if (lo_inf1 != end) lo_inf = lo_inf1;
if (lo_sup1 != end) lo_sup = lo_sup1;
if (hi_inf1 != end) hi_inf = hi_inf1;

View file

@ -1156,7 +1156,7 @@ namespace smt {
return literal(ctx.mk_bool_var(y));
}
literal max(literal a, literal b) {
literal mk_max(literal a, literal b) {
if (a == b) return a;
expr_ref t1(m), t2(m), t3(m);
ctx.literal2expr(a, t1);
@ -1166,7 +1166,7 @@ namespace smt {
return literal(v);
}
literal min(literal a, literal b) {
literal mk_min(literal a, literal b) {
if (a == b) return a;
expr_ref t1(m), t2(m), t3(m);
ctx.literal2expr(a, t1);
@ -1176,6 +1176,8 @@ namespace smt {
return literal(v);
}
literal mk_not(literal a) { return ~a; }
void mk_clause(unsigned n, literal const* ls) {
literal_vector tmp(n, ls);
ctx.mk_clause(n, tmp.c_ptr(), 0, CLS_AUX, 0);

View file

@ -39,8 +39,55 @@ namespace pb {
m(m),
au(m),
pb(m),
bv(m)
bv(m),
m_sort(*this),
m_lemmas(m),
m_trail(m)
{}
void card2bv_rewriter::mk_assert(func_decl * f, unsigned sz, expr * const* args, expr_ref & result, expr_ref_vector& lemmas) {
m_lemmas.reset();
SASSERT(f->get_family_id() == pb.get_family_id());
if (is_or(f)) {
result = m.mk_or(sz, args);
}
else if (is_and(f)) {
result = m.mk_and(sz, args);
}
else if (pb.is_eq(f) && pb.get_k(f).is_unsigned() && pb.has_unit_coefficients(f)) {
result = m_sort.eq(pb.get_k(f).get_unsigned(), sz, args);
}
else if (pb.is_le(f) && pb.get_k(f).is_unsigned() && pb.has_unit_coefficients(f)) {
result = m_sort.le(false, pb.get_k(f).get_unsigned(), sz, args);
}
else if (pb.is_ge(f) && pb.get_k(f).is_unsigned() && pb.has_unit_coefficients(f)) {
result = m_sort.ge(false, pb.get_k(f).get_unsigned(), sz, args);
}
else {
br_status st = mk_shannon(f, sz, args, result);
if (st == BR_FAILED) {
mk_bv(f, sz, args, result);
}
}
lemmas.append(m_lemmas);
}
std::ostream& card2bv_rewriter::pp(std::ostream& out, literal lit) {
return out << mk_ismt2_pp(lit, m);
}
card2bv_rewriter::literal card2bv_rewriter::trail(literal l) {
m_trail.push_back(l);
return l;
}
card2bv_rewriter::literal card2bv_rewriter::fresh() {
return trail(m.mk_fresh_const("sn", m.mk_bool_sort()));
}
void card2bv_rewriter::mk_clause(unsigned n, literal const* lits) {
m_lemmas.push_back(m.mk_or_reduced(n, lits));
}
br_status card2bv_rewriter::mk_app_core(func_decl * f, unsigned sz, expr * const* args, expr_ref & result) {
if (f->get_family_id() == null_family_id) {
@ -69,7 +116,8 @@ namespace pb {
}
br_status st = mk_shannon(f, sz, args, result);
if (st == BR_FAILED) {
return mk_bv(f, sz, args, result);
mk_bv(f, sz, args, result);
return BR_DONE;
}
else {
return st;
@ -135,7 +183,7 @@ namespace pb {
return false;
}
br_status card2bv_rewriter::mk_bv(func_decl * f, unsigned sz, expr * const* args, expr_ref & result) {
void card2bv_rewriter::mk_bv(func_decl * f, unsigned sz, expr * const* args, expr_ref & result) {
expr_ref zero(m), a(m), b(m);
expr_ref_vector es(m);
unsigned bw = get_num_bits(f);
@ -172,7 +220,6 @@ namespace pb {
default:
UNREACHABLE();
}
return BR_DONE;
}
struct argc_t {
@ -352,10 +399,30 @@ namespace pb {
if (m.is_true(lo)) return m.mk_implies(c, hi);
return m.mk_ite(c, hi, lo);
}
void card_pb_rewriter::rewrite(expr* e, expr_ref& result) {
if (pb.is_eq(e)) {
app* a = to_app(e);
ast_manager& m = m_lemmas.get_manager();
unsigned sz = a->get_num_args();
expr_ref_vector args(m);
expr_ref tmp(m);
for (unsigned i = 0; i < sz; ++i) {
(*this)(a->get_arg(i), tmp);
args.push_back(tmp);
}
m_cfg.m_r.mk_assert(a->get_decl(), sz, args.c_ptr(), result, m_lemmas);
}
else {
(*this)(e, result);
}
}
};
template class rewriter_tpl<pb::card2bv_rewriter_cfg>;
class card2bv_tactic : public tactic {
ast_manager & m;
params_ref m_params;
@ -402,6 +469,7 @@ public:
tactic_report report("card2bv", *g);
m_rw1.reset();
m_rw2.reset();
m_rw2.lemmas().reset();
if (g->inconsistent()) {
result.push_back(g.get());
@ -413,9 +481,12 @@ public:
for (unsigned idx = 0; idx < size; idx++) {
m_rw1(g->form(idx), new_f1);
TRACE("card2bv", tout << "Rewriting " << mk_ismt2_pp(new_f1.get(), m) << std::endl;);
m_rw2(new_f1, new_f2);
m_rw2.rewrite(new_f1, new_f2);
g->update(idx, new_f2, g->pr(idx), g->dep(idx));
}
for (unsigned i = 0; i < m_rw2.lemmas().size(); ++i) {
g->assert_expr(m_rw2.lemmas()[i].get());
}
g->inc_depth();
result.push_back(g.get());

View file

@ -23,6 +23,9 @@ Notes:
#include"pb_decl_plugin.h"
#include"th_rewriter.h"
#include"rewriter.h"
#include<typeinfo>
#include"sorting_network.h"
class ast_manager;
class tactic;
@ -30,12 +33,20 @@ class tactic;
namespace pb {
class card2bv_rewriter {
public:
typedef expr* literal;
typedef ptr_vector<expr> literal_vector;
private:
ast_manager& m;
arith_util au;
pb_util pb;
bv_util bv;
psort_nw<card2bv_rewriter> m_sort;
expr_ref_vector m_lemmas;
expr_ref_vector m_trail;
unsigned get_num_bits(func_decl* f);
br_status mk_bv(func_decl * f, unsigned sz, expr * const* args, expr_ref & result);
void mk_bv(func_decl * f, unsigned sz, expr * const* args, expr_ref & result);
br_status mk_shannon(func_decl * f, unsigned sz, expr * const* args, expr_ref & result);
expr* negate(expr* e);
expr* mk_ite(expr* c, expr* hi, expr* lo);
@ -45,6 +56,19 @@ namespace pb {
public:
card2bv_rewriter(ast_manager& m);
br_status mk_app_core(func_decl * f, unsigned sz, expr * const* args, expr_ref & result);
void mk_assert(func_decl * f, unsigned sz, expr * const* args, expr_ref & result, expr_ref_vector& lemmas);
// definitions used for sorting network
literal mk_false() { return m.mk_false(); }
literal mk_true() { return m.mk_true(); }
literal mk_max(literal a, literal b) { return trail(m.mk_or(a, b)); }
literal mk_min(literal a, literal b) { return trail(m.mk_and(a, b)); }
literal mk_not(literal a) { if (m.is_not(a,a)) return a; return trail(m.mk_not(a)); }
std::ostream& pp(std::ostream& out, literal lit);
literal fresh();
literal trail(literal l);
void mk_clause(unsigned n, literal const* lits);
};
struct card2bv_rewriter_cfg : public default_rewriter_cfg {
@ -55,15 +79,23 @@ namespace pb {
result_pr = 0;
return m_r.mk_app_core(f, num, args, result);
}
card2bv_rewriter_cfg(ast_manager & m):m_r(m) {}
card2bv_rewriter_cfg(ast_manager & m):m_r(m) {}
};
class card_pb_rewriter : public rewriter_tpl<card2bv_rewriter_cfg> {
card2bv_rewriter_cfg m_cfg;
pb_util pb;
expr_ref_vector m_lemmas;
public:
card_pb_rewriter(ast_manager & m):
rewriter_tpl<card2bv_rewriter_cfg>(m, false, m_cfg),
m_cfg(m) {}
card_pb_rewriter(ast_manager & m):
rewriter_tpl<card2bv_rewriter_cfg>(m, false, m_cfg),
m_cfg(m),
pb(m),
m_lemmas(m) {}
void rewrite(expr* e, expr_ref& result);
expr_ref_vector& lemmas() { return m_lemmas; }
};
};

View file

@ -556,7 +556,7 @@ static void test_A_5_5_3() {
for (unsigned k = 1; k <= 5; ++k) {
for (unsigned l = 1; l <= 5; ++l) {
for (unsigned j = 1; j <= 3; ++j) {
bool one = ((j*k <= i) && (((i - j) % 3) == 0); // fixme
bool one = ((j*k <= i) && (((i - j) % 3) == 0)); // fixme
v.push_back(rational(one));
}
}

View file

@ -1,9 +1,13 @@
#include "sorting_network.h"
#include "trace.h"
#include "vector.h"
#include "ast.h"
#include "ast_pp.h"
#include "reg_decl_plugins.h"
#include "sorting_network.h"
#include "smt_kernel.h"
#include "model_smt2_pp.h"
#include "smt_params.h"
struct ast_ext {
@ -26,6 +30,8 @@ struct ast_ext {
}
};
struct unsigned_ext {
unsigned_ext() {}
typedef unsigned T;
@ -41,6 +47,7 @@ struct unsigned_ext {
}
};
static void is_sorted(svector<unsigned> const& v) {
for (unsigned i = 0; i + 1 < v.size(); ++i) {
SASSERT(v[i] <= v[i+1]);
@ -134,9 +141,97 @@ void test_sorting3() {
}
}
struct ast_ext2 {
ast_manager& m;
expr_ref_vector m_clauses;
expr_ref_vector m_trail;
ast_ext2(ast_manager& m):m(m), m_clauses(m), m_trail(m) {}
typedef expr* literal;
typedef ptr_vector<expr> literal_vector;
expr* trail(expr* e) {
m_trail.push_back(e);
return e;
}
literal mk_false() { return m.mk_false(); }
literal mk_true() { return m.mk_true(); }
literal mk_max(literal a, literal b) {
return trail(m.mk_or(a, b));
}
literal mk_min(literal a, literal b) { return trail(m.mk_and(a, b)); }
literal mk_not(literal a) { if (m.is_not(a,a)) return a;
return trail(m.mk_not(a));
}
std::ostream& pp(std::ostream& out, literal lit) {
return out << mk_pp(lit, m);
}
literal fresh() {
return trail(m.mk_fresh_const("x", m.mk_bool_sort()));
}
void mk_clause(unsigned n, literal const* lits) {
m_clauses.push_back(m.mk_or_reduced(n, lits));
}
};
void test_sorting5(unsigned n, unsigned k) {
std::cout << "n: " << n << " k: " << k << "\n";
SASSERT(k < n);
ast_manager m;
reg_decl_plugins(m);
ast_ext2 ext(m);
expr_ref_vector in(m), out(m);
for (unsigned i = 0; i < n; ++i) {
in.push_back(m.mk_fresh_const("a",m.mk_bool_sort()));
}
smt_params fp;
smt::kernel solver(m, fp);
psort_nw<ast_ext2> sn(ext);
expr_ref result(m);
result = sn.eq(k, in.size(), in.c_ptr());
solver.assert_expr(result);
for (unsigned i = 0; i < ext.m_clauses.size(); ++i) {
solver.assert_expr(ext.m_clauses[i].get());
}
lbool res = solver.check();
SASSERT(res == l_true);
std::cout << res << "\n";
solver.push();
for (unsigned i = 0; i < k; ++i) {
solver.assert_expr(in[i].get());
}
res = solver.check();
SASSERT(res == l_true);
solver.assert_expr(in[k].get());
res = solver.check();
if (res == l_true) {
TRACE("pb",
unsigned sz = solver.size();
for (unsigned i = 0; i < sz; ++i) {
tout << mk_pp(solver.get_formulas()[i], m) << "\n";
});
model_ref model;
solver.get_model(model);
model_smt2_pp(std::cout, m, *model, 0);
TRACE("pb", model_smt2_pp(tout, m, *model, 0););
}
SASSERT(res == l_false);
solver.pop(1);
}
void tst_sorting_network() {
test_sorting1();
test_sorting2();
test_sorting3();
test_sorting4();
test_sorting5(7,6);
for (unsigned n = 3; n < 10; n += 2) {
for (unsigned k = 1; k < n; ++k) {
test_sorting5(n, k);
}
}
}

View file

@ -144,7 +144,7 @@ Notes:
}
};
static vc min(vc const& v1, vc const& v2) {
static vc mk_min(vc const& v1, vc const& v2) {
return (v1.to_int() < v2.to_int())?v1:v2;
}
@ -205,7 +205,7 @@ Notes:
SASSERT(2*k <= n);
m_t = full?LE_FULL:LE;
card(k + 1, n, xs, out);
return ~out[k];
return ctx.mk_not(out[k]);
}
}
@ -219,11 +219,11 @@ Notes:
return eq(k, n, in.c_ptr());
}
else {
SASSERT(2*k < n);
SASSERT(2*k <= n);
m_t = EQ;
card(k+1, n, xs, out);
SASSERT(out.size() >= k+1);
return out[k-1]; // & ~out[m] TBD
return ctx.mk_min(out[k-1], ctx.mk_not(out[k]));
}
}
@ -253,10 +253,10 @@ Notes:
}
k = N - k;
for (unsigned i = 0; i < N; ++i) {
in.push_back(~xs[i]);
in.push_back(ctx.mk_not(xs[i]));
}
TRACE("pb",
pp(tout << N << ": ", in);
pp(tout << N << ": ", in);
tout << " ~ " << k << "\n";);
return true;
}
@ -269,16 +269,16 @@ Notes:
unsigned power2(unsigned n) const { SASSERT(n < 10); return 1 << n; }
literal max(literal a, literal b) {
literal mk_max(literal a, literal b) {
if (a == b) return a;
m_stats.m_num_compiled_vars++;
return ctx.max(a, b);
return ctx.mk_max(a, b);
}
literal min(literal a, literal b) {
literal mk_min(literal a, literal b) {
if (a == b) return a;
m_stats.m_num_compiled_vars++;
return ctx.min(a, b);
return ctx.mk_min(a, b);
}
literal fresh() {
@ -299,20 +299,20 @@ Notes:
ctx.mk_clause(n, tmp.c_ptr());
}
// y1 <= max(x1,x2)
// y2 <= min(x1,x2)
// y1 <= mk_max(x1,x2)
// y2 <= mk_min(x1,x2)
void cmp_ge(literal x1, literal x2, literal y1, literal y2) {
add_clause(~y2, x1);
add_clause(~y2, x2);
add_clause(~y1, x1, x2);
add_clause(ctx.mk_not(y2), x1);
add_clause(ctx.mk_not(y2), x2);
add_clause(ctx.mk_not(y1), x1, x2);
}
// max(x1,x2) <= y1
// min(x1,x2) <= y2
// mk_max(x1,x2) <= y1
// mk_min(x1,x2) <= y2
void cmp_le(literal x1, literal x2, literal y1, literal y2) {
add_clause(~x1, y1);
add_clause(~x2, y1);
add_clause(~x1, ~x2, y2);
add_clause(ctx.mk_not(x1), y1);
add_clause(ctx.mk_not(x2), y1);
add_clause(ctx.mk_not(x1), ctx.mk_not(x2), y2);
}
void cmp_eq(literal x1, literal x2, literal y1, literal y2) {
@ -376,8 +376,8 @@ Notes:
literal_vector& out) {
TRACE("pb", tout << "merge a: " << a << " b: " << b << "\n";);
if (a == 1 && b == 1) {
literal y1 = max(as[0], bs[0]);
literal y2 = min(as[0], bs[0]);
literal y1 = mk_max(as[0], bs[0]);
literal y2 = mk_min(as[0], bs[0]);
out.push_back(y1);
out.push_back(y2);
psort_nw<psort_expr>::cmp(as[0], bs[0], y1, y2);
@ -453,8 +453,8 @@ Notes:
out.push_back(as[0]);
unsigned sz = std::min(as.size()-1, bs.size());
for (unsigned i = 0; i < sz; ++i) {
literal y1 = max(as[i+1],bs[i]);
literal y2 = min(as[i+1],bs[i]);
literal y1 = mk_max(as[i+1],bs[i]);
literal y2 = mk_min(as[i+1],bs[i]);
psort_nw<psort_expr>::cmp(as[i+1], bs[i], y1, y2);
out.push_back(y1);
out.push_back(y2);
@ -539,16 +539,16 @@ Notes:
literal_vector& out) {
TRACE("pb", tout << "smerge: c:" << c << " a:" << a << " b:" << b << "\n";);
if (a == 1 && b == 1 && c == 1) {
literal y = max(as[0], bs[0]);
literal y = mk_max(as[0], bs[0]);
if (m_t != GE) {
// x1 <= max(x1,x2)
// x2 <= max(x1,x2)
add_clause(~as[0], y);
add_clause(~bs[0], y);
// x1 <= mk_max(x1,x2)
// x2 <= mk_max(x1,x2)
add_clause(ctx.mk_not(as[0]), y);
add_clause(ctx.mk_not(bs[0]), y);
}
if (m_t != LE) {
// max(x1,x2) <= x1, x2
add_clause(~y, as[0], bs[0]);
// mk_max(x1,x2) <= x1, x2
add_clause(ctx.mk_not(y), as[0], bs[0]);
}
out.push_back(y);
}
@ -597,13 +597,13 @@ Notes:
literal z2 = out2.back();
out1.pop_back();
out2.pop_back();
y = max(z1, z2);
y = mk_max(z1, z2);
if (m_t != GE) {
add_clause(~z1, y);
add_clause(~z2, y);
add_clause(ctx.mk_not(z1), y);
add_clause(ctx.mk_not(z2), y);
}
if (m_t != LE) {
add_clause(~y, z1, z2);
add_clause(ctx.mk_not(y), z1, z2);
}
}
interleave(out1, out2, out);
@ -664,31 +664,28 @@ Notes:
}
if (m_t != GE) {
for (unsigned i = 0; i < a; ++i) {
add_clause(~as[i], out[i]);
add_clause(ctx.mk_not(as[i]), out[i]);
}
for (unsigned i = 0; i < b; ++i) {
add_clause(~bs[i], out[i]);
add_clause(ctx.mk_not(bs[i]), out[i]);
}
for (unsigned i = 1; i <= a; ++i) {
for (unsigned j = 1; j <= b && i + j <= c; ++j) {
add_clause(~as[i-1],~bs[j-1],out[i+j-1]);
add_clause(ctx.mk_not(as[i-1]),ctx.mk_not(bs[j-1]),out[i+j-1]);
}
}
}
if (m_t != LE) {
for (unsigned k = 1; k <= c; ++k) {
literal_vector ls;
ls.push_back(~out[k-1]);
if (k <= a) {
ls.push_back(as[k-1]);
}
if (k <= b) {
ls.push_back(bs[k-1]);
}
for (unsigned i = 1; i <= std::min(a,k-1); ++i) {
if (k + 1 - i <= b) {
ls.push_back(as[i-1]);
ls.push_back(bs[k-i]);
literal_vector ls;
for (unsigned k = 0; k < c; ++k) {
ls.reset();
ls.push_back(ctx.mk_not(out[k]));
for (unsigned i = 0; i < std::min(a,k + 1); ++i) {
unsigned j = k - i;
SASSERT(i + j == k);
if (j < b) {
ls.push_back(as[i]);
ls.push_back(bs[j]);
add_clause(ls.size(), ls.c_ptr());
ls.pop_back();
ls.pop_back();
@ -726,7 +723,7 @@ Notes:
}
if (m_t != LE) {
for (unsigned k = 1; k <= m; ++k) {
lits.push_back(~out[k-1]);
lits.push_back(ctx.mk_not(out[k-1]));
add_subset(false, n-k+1, 0, lits, n, xs);
lits.pop_back();
}
@ -754,7 +751,7 @@ Notes:
return;
}
for (unsigned i = offset; i < n - k + 1; ++i) {
lits.push_back(polarity?~xs[i]:xs[i]);
lits.push_back(polarity?ctx.mk_not(xs[i]):xs[i]);
add_subset(polarity, k-1, i+1, lits, n, xs);
lits.pop_back();
}