3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-12 12:08:18 +00:00

re-add pb extraction

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2020-08-26 13:52:43 -07:00
parent 9c77fbc2a9
commit 526d76b447
7 changed files with 118 additions and 94 deletions

View file

@ -13,8 +13,7 @@ Author:
Nikolaj Bjorner (nbjorner) 2015-12-5 Nikolaj Bjorner (nbjorner) 2015-12-5
Murphy Berzish 2017-02-21 Murphy Berzish 2017-02-21
Caleb Stanford 2020-07-07
Notes:
--*/ --*/

View file

@ -5052,6 +5052,91 @@ namespace sat {
return ok; return ok;
} }
bool ba_solver::extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& add_cardinality,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& add_pb) {
unsigned_vector coeffs;
literal_vector lits;
for (constraint* cp : m_constraints) {
switch (cp->tag()) {
case card_t: {
card const& c = cp->to_card();
unsigned n = c.size();
unsigned k = c.k();
if (c.lit() == null_literal) {
// c.lits() >= k
// <=>
// ~c.lits() <= n - k
lits.reset();
for (unsigned j = 0; j < n; ++j) lits.push_back(c[j]);
add_cardinality(lits.size(), lits.c_ptr(), n - k);
}
else {
//
// c.lit() <=> c.lits() >= k
//
// (c.lits() < k) or c.lit()
// = (c.lits() + (n - k + 1)*~c.lit()) <= n
//
// ~c.lit() or (c.lits() >= k)
// = ~c.lit() or (~c.lits() <= n - k)
// = k*c.lit() + ~c.lits() <= n
//
lits.reset();
coeffs.reset();
for (literal l : c) lits.push_back(l), coeffs.push_back(1);
lits.push_back(~c.lit()); coeffs.push_back(n - k + 1);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), n);
lits.reset();
coeffs.reset();
for (literal l : c) lits.push_back(~l), coeffs.push_back(1);
lits.push_back(c.lit()); coeffs.push_back(k);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), n);
}
break;
}
case ba_solver::pb_t: {
ba_solver::pb const& p = cp->to_pb();
lits.reset();
coeffs.reset();
unsigned sum = 0;
for (ba_solver::wliteral wl : p) sum += wl.first;
if (p.lit() == null_literal) {
// w1 + .. + w_n >= k
// <=>
// ~wl + ... + ~w_n <= sum_of_weights - k
for (ba_solver::wliteral wl : p) lits.push_back(~(wl.second)), coeffs.push_back(wl.first);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), sum - p.k());
}
else {
// lit <=> w1 + .. + w_n >= k
// <=>
// lit or w1 + .. + w_n <= k - 1
// ~lit or w1 + .. + w_n >= k
// <=>
// (sum - k + 1)*~lit + w1 + .. + w_n <= sum
// k*lit + ~wl + ... + ~w_n <= sum
lits.push_back(p.lit()), coeffs.push_back(p.k());
for (ba_solver::wliteral wl : p) lits.push_back(~(wl.second)), coeffs.push_back(wl.first);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), sum);
lits.reset();
coeffs.reset();
lits.push_back(~p.lit()), coeffs.push_back(sum + 1 - p.k());
for (ba_solver::wliteral wl : p) lits.push_back(wl.second), coeffs.push_back(wl.first);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), sum);
}
break;
}
case ba_solver::xr_t:
return false;
}
}
return true;
}
}; };

View file

@ -579,6 +579,9 @@ namespace sat {
bool validate() override; bool validate() override;
bool extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& add_cardinlaity,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& add_pb) override;
}; };

View file

@ -419,4 +419,13 @@ namespace euf {
return nullptr; return nullptr;
} }
bool solver::extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& card,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) {
if (m_true)
return false;
for (auto* e : m_extensions)
if (!e->extract_pb(card, pb))
return false;
return true;
}
} }

View file

@ -131,6 +131,10 @@ namespace euf {
bool check_model(sat::model const& m) const override; bool check_model(sat::model const& m) const override;
unsigned max_var(unsigned w) const override; unsigned max_var(unsigned w) const override;
bool extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& card,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) override;
sat::literal internalize(sat::sat_internalizer& si, expr* e, bool sign, bool root) override; sat::literal internalize(sat::sat_internalizer& si, expr* e, bool sign, bool root) override;
model_converter* get_model(); model_converter* get_model();

View file

@ -18,6 +18,7 @@ Revision History:
--*/ --*/
#pragma once #pragma once
#include <functional>
#include "sat/sat_types.h" #include "sat/sat_types.h"
#include "util/params.h" #include "util/params.h"
#include "util/statistics.h" #include "util/statistics.h"
@ -83,6 +84,11 @@ namespace sat {
virtual bool is_blocked(literal l, ext_constraint_idx) = 0; virtual bool is_blocked(literal l, ext_constraint_idx) = 0;
virtual bool check_model(model const& m) const = 0; virtual bool check_model(model const& m) const = 0;
virtual unsigned max_var(unsigned w) const = 0; virtual unsigned max_var(unsigned w) const = 0;
virtual bool extract_pb(std::function<void(unsigned sz, literal const* c, unsigned k)>& card,
std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)>& pb) {
return true;
}
}; };
}; };

View file

@ -322,6 +322,7 @@ namespace sat {
add_unit(~c[0], null_literal); add_unit(~c[0], null_literal);
return; return;
} }
m_is_pb = true;
unsigned id = m_constraints.size(); unsigned id = m_constraints.size();
m_constraints.push_back(constraint(k, id)); m_constraints.push_back(constraint(k, id));
for (unsigned i = 0; i < sz; ++i) { for (unsigned i = 0; i < sz; ++i) {
@ -414,98 +415,15 @@ namespace sat {
} }
m_num_non_binary_clauses = s.m_clauses.size(); m_num_non_binary_clauses = s.m_clauses.size();
if (s.get_extension())
throw default_exception("local search is incompatible with extensions");
#if 0
// copy cardinality clauses // copy cardinality clauses
ba_solver* ext = dynamic_cast<ba_solver*>(s.get_extension()); extension* ext = s.get_extension();
if (ext) { std::function<void(unsigned, literal const*, unsigned)> card =
unsigned_vector coeffs; [&](unsigned sz, literal const* c, unsigned k) { add_cardinality(sz, c, k); };
literal_vector lits; std::function<void(unsigned sz, literal const* c, unsigned const* coeffs, unsigned k)> pb =
for (ba_solver::constraint* cp : ext->m_constraints) { [&](unsigned sz, literal const* c, unsigned const* coeffs, unsigned k) { add_pb(sz, c, coeffs, k); };
switch (cp->tag()) { if (ext && !ext->extract_pb(card, pb))
case ba_solver::card_t: { throw default_exception("local search is incomplete with extensions beyond PB");
ba_solver::card const& c = cp->to_card();
unsigned n = c.size();
unsigned k = c.k();
if (c.lit() == null_literal) {
// c.lits() >= k
// <=>
// ~c.lits() <= n - k
lits.reset();
for (unsigned j = 0; j < n; ++j) lits.push_back(c[j]);
add_cardinality(lits.size(), lits.c_ptr(), n - k);
}
else {
//
// c.lit() <=> c.lits() >= k
//
// (c.lits() < k) or c.lit()
// = (c.lits() + (n - k + 1)*~c.lit()) <= n
//
// ~c.lit() or (c.lits() >= k)
// = ~c.lit() or (~c.lits() <= n - k)
// = k*c.lit() + ~c.lits() <= n
//
m_is_pb = true;
lits.reset();
coeffs.reset();
for (literal l : c) lits.push_back(l), coeffs.push_back(1);
lits.push_back(~c.lit()); coeffs.push_back(n - k + 1);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), n);
lits.reset();
coeffs.reset();
for (literal l : c) lits.push_back(~l), coeffs.push_back(1);
lits.push_back(c.lit()); coeffs.push_back(k);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), n);
}
break;
}
case ba_solver::pb_t: {
ba_solver::pb const& p = cp->to_pb();
lits.reset();
coeffs.reset();
m_is_pb = true;
unsigned sum = 0;
for (ba_solver::wliteral wl : p) sum += wl.first;
if (p.lit() == null_literal) {
// w1 + .. + w_n >= k
// <=>
// ~wl + ... + ~w_n <= sum_of_weights - k
for (ba_solver::wliteral wl : p) lits.push_back(~(wl.second)), coeffs.push_back(wl.first);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), sum - p.k());
}
else {
// lit <=> w1 + .. + w_n >= k
// <=>
// lit or w1 + .. + w_n <= k - 1
// ~lit or w1 + .. + w_n >= k
// <=>
// (sum - k + 1)*~lit + w1 + .. + w_n <= sum
// k*lit + ~wl + ... + ~w_n <= sum
lits.push_back(p.lit()), coeffs.push_back(p.k());
for (ba_solver::wliteral wl : p) lits.push_back(~(wl.second)), coeffs.push_back(wl.first);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), sum);
lits.reset();
coeffs.reset();
lits.push_back(~p.lit()), coeffs.push_back(sum + 1 - p.k());
for (ba_solver::wliteral wl : p) lits.push_back(wl.second), coeffs.push_back(wl.first);
add_pb(lits.size(), lits.c_ptr(), coeffs.c_ptr(), sum);
}
break;
}
case ba_solver::xr_t:
throw default_exception("local search is incompatible with enabling xor solving");
break;
}
}
}
#endif
if (_init) { if (_init) {
init(); init();