mirror of
https://github.com/Z3Prover/z3
synced 2025-06-21 13:23:39 +00:00
working on pb sls
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
parent
9811054e72
commit
94b3a46811
1 changed files with 177 additions and 9 deletions
|
@ -1,6 +1,7 @@
|
||||||
#include "pb_sls.h"
|
#include "pb_sls.h"
|
||||||
#include "smt_literal.h"
|
#include "smt_literal.h"
|
||||||
#include "ast_pp.h"
|
#include "ast_pp.h"
|
||||||
|
#include "uint_set.h"
|
||||||
|
|
||||||
namespace smt {
|
namespace smt {
|
||||||
struct pb_sls::imp {
|
struct pb_sls::imp {
|
||||||
|
@ -41,21 +42,29 @@ namespace smt {
|
||||||
vector<clause> m_clauses; // clauses to be satisfied
|
vector<clause> m_clauses; // clauses to be satisfied
|
||||||
vector<clause> m_soft; // soft constraints
|
vector<clause> m_soft; // soft constraints
|
||||||
vector<rational> m_weights; // weights of soft constraints
|
vector<rational> m_weights; // weights of soft constraints
|
||||||
rational m_value; // current value of soft constraints
|
rational m_penalty; // current penalty of soft constraints
|
||||||
vector<unsigned_vector> m_pos, m_neg; // positive and negative occurs.
|
vector<unsigned_vector> m_hard_occ, m_soft_occ; // variable occurrence
|
||||||
svector<bool> m_assignment; // current assignment.
|
svector<bool> m_assignment; // current assignment.
|
||||||
obj_map<expr, unsigned> m_expr2var; // map expressions to Boolean variables.
|
obj_map<expr, unsigned> m_expr2var; // map expressions to Boolean variables.
|
||||||
ptr_vector<expr> m_var2expr; // reverse map
|
ptr_vector<expr> m_var2expr; // reverse map
|
||||||
|
uint_set m_hard_false; // list of hard clauses that are false.
|
||||||
|
uint_set m_soft_false; // list of soft clauses that are false.
|
||||||
|
unsigned m_max_flips;
|
||||||
imp(ast_manager& m):
|
imp(ast_manager& m):
|
||||||
m(m),
|
m(m),
|
||||||
pb(m),
|
pb(m),
|
||||||
m_cancel(false)
|
m_cancel(false)
|
||||||
{}
|
{
|
||||||
|
m_max_flips = 100;
|
||||||
|
}
|
||||||
|
|
||||||
~imp() {
|
~imp() {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsigned max_flips() {
|
||||||
|
return m_max_flips;
|
||||||
|
}
|
||||||
|
|
||||||
void add(expr* f) {
|
void add(expr* f) {
|
||||||
clause cls(mgr);
|
clause cls(mgr);
|
||||||
if (compile_clause(f, cls)) {
|
if (compile_clause(f, cls)) {
|
||||||
|
@ -72,12 +81,17 @@ namespace smt {
|
||||||
void init_value(expr* f, bool b) {
|
void init_value(expr* f, bool b) {
|
||||||
literal lit = mk_literal(f);
|
literal lit = mk_literal(f);
|
||||||
SASSERT(!lit.sign());
|
SASSERT(!lit.sign());
|
||||||
//if (m_assignment[lit.var()] != b) {
|
|
||||||
m_assignment[lit.var()] = b;
|
m_assignment[lit.var()] = b;
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lbool operator()() {
|
lbool operator()() {
|
||||||
|
init();
|
||||||
|
for (unsigned i = 0; i < max_flips(); ++i) {
|
||||||
|
flip();
|
||||||
|
if (m_cancel) {
|
||||||
|
return l_undef;
|
||||||
|
}
|
||||||
|
}
|
||||||
return l_undef;
|
return l_undef;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -102,6 +116,157 @@ namespace smt {
|
||||||
void updt_params(params_ref& p) {
|
void updt_params(params_ref& p) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool eval(clause& cls) {
|
||||||
|
unsigned sz = cls.m_lits.size();
|
||||||
|
cls.m_value.reset();
|
||||||
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
|
if (get_value(cls.m_lits[i])) {
|
||||||
|
cls.m_value += cls.m_weights[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (cls.m_eq) {
|
||||||
|
return cls.m_value == cls.m_k;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return cls.m_value >= cls.m_k;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init_occ(vector<clause> const& clauses, vector<unsigned_vector> & occ) {
|
||||||
|
for (unsigned i = 0; i < clauses.size(); ++i) {
|
||||||
|
clause const& cls = clauses[i];
|
||||||
|
for (unsigned j = 0; j < cls.m_lits.size(); ++j) {
|
||||||
|
literal lit = cls.m_lits[j];
|
||||||
|
occ[lit.var()].push_back(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void init() {
|
||||||
|
// initialize the occurs vectors.
|
||||||
|
init_occ(m_clauses, m_hard_occ);
|
||||||
|
init_occ(m_soft, m_soft_occ);
|
||||||
|
// add clauses that are false.
|
||||||
|
for (unsigned i = 0; i < m_clauses.size(); ++i) {
|
||||||
|
if (!eval(m_clauses[i])) {
|
||||||
|
m_hard_false.insert(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
m_penalty.reset();
|
||||||
|
for (unsigned i = 0; i < m_soft.size(); ++i) {
|
||||||
|
if (!eval(m_soft[i])) {
|
||||||
|
m_soft_false.insert(i);
|
||||||
|
m_penalty += m_weights[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flip() {
|
||||||
|
if (m_hard_false.empty()) {
|
||||||
|
flip_soft();
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
flip_hard();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void flip_hard() {
|
||||||
|
SASSERT(!m_hard_false.empty());
|
||||||
|
clause const& cls = pick_hard_clause();
|
||||||
|
int break_count;
|
||||||
|
int min_bc = INT_MAX;
|
||||||
|
unsigned min_bc_index = 0;
|
||||||
|
for (unsigned i = 0; i < cls.m_lits.size(); ++i) {
|
||||||
|
literal lit = cls.m_lits[i];
|
||||||
|
break_count = flip(lit);
|
||||||
|
if (break_count <= 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (break_count < min_bc) {
|
||||||
|
min_bc = break_count;
|
||||||
|
min_bc_index = i;
|
||||||
|
}
|
||||||
|
VERIFY(-break_count == flip(~lit));
|
||||||
|
}
|
||||||
|
// just do a greedy move:
|
||||||
|
flip(cls.m_lits[min_bc_index]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void flip_soft() {
|
||||||
|
NOT_IMPLEMENTED_YET();
|
||||||
|
}
|
||||||
|
|
||||||
|
// crude selection strategy.
|
||||||
|
clause const& pick_hard_clause() {
|
||||||
|
SASSERT(!m_hard_false.empty());
|
||||||
|
uint_set::iterator it = m_hard_false.begin();
|
||||||
|
uint_set::iterator end = m_hard_false.end();
|
||||||
|
SASSERT(it != end);
|
||||||
|
return m_clauses[*it];
|
||||||
|
}
|
||||||
|
|
||||||
|
clause const& pick_soft_clause() {
|
||||||
|
SASSERT(!m_soft_false.empty());
|
||||||
|
uint_set::iterator it = m_soft_false.begin();
|
||||||
|
uint_set::iterator end = m_soft_false.end();
|
||||||
|
SASSERT(it != end);
|
||||||
|
unsigned index = *it;
|
||||||
|
rational penalty = m_weights[index];
|
||||||
|
++it;
|
||||||
|
for (; it != end; ++it) {
|
||||||
|
if (m_weights[*it] > penalty) {
|
||||||
|
index = *it;
|
||||||
|
penalty = m_weights[*it];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return m_soft[index];
|
||||||
|
}
|
||||||
|
|
||||||
|
int flip(literal l) {
|
||||||
|
SASSERT(get_value(l));
|
||||||
|
m_assignment[l.var()] = !m_assignment[l.var()];
|
||||||
|
int break_count = 0;
|
||||||
|
{
|
||||||
|
unsigned_vector const& occ = m_hard_occ[l.var()];
|
||||||
|
for (unsigned i = 0; i < occ.size(); ++i) {
|
||||||
|
unsigned j = occ[i];
|
||||||
|
if (eval(m_clauses[j])) {
|
||||||
|
if (m_hard_false.contains(j)) {
|
||||||
|
break_count--;
|
||||||
|
m_hard_false.remove(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!m_hard_false.contains(j)) {
|
||||||
|
break_count++;
|
||||||
|
m_hard_false.insert(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{
|
||||||
|
unsigned_vector const& occ = m_soft_occ[l.var()];
|
||||||
|
for (unsigned i = 0; i < occ.size(); ++i) {
|
||||||
|
unsigned j = occ[i];
|
||||||
|
if (eval(m_soft[j])) {
|
||||||
|
if (m_soft_false.contains(j)) {
|
||||||
|
m_penalty -= m_weights[j];
|
||||||
|
m_soft_false.remove(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!m_soft_false.contains(j)) {
|
||||||
|
m_penalty += m_weights[j];
|
||||||
|
m_soft_false.insert(j);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
SASSERT(get_value(~l));
|
||||||
|
return break_count;
|
||||||
|
}
|
||||||
|
|
||||||
literal mk_literal(expr* f) {
|
literal mk_literal(expr* f) {
|
||||||
literal result;
|
literal result;
|
||||||
bool sign = false;
|
bool sign = false;
|
||||||
|
@ -117,10 +282,10 @@ namespace smt {
|
||||||
else {
|
else {
|
||||||
unsigned var;
|
unsigned var;
|
||||||
if (!m_expr2var.find(f, var)) {
|
if (!m_expr2var.find(f, var)) {
|
||||||
var = m_pos.size();
|
var = m_hard_occ.size();
|
||||||
SASSERT(m_expr2var.size() == var);
|
SASSERT(m_expr2var.size() == var);
|
||||||
m_pos.push_back(unsigned_vector());
|
m_hard_occ.push_back(unsigned_vector());
|
||||||
m_neg.push_back(unsigned_vector());
|
m_soft_occ.push_back(unsigned_vector());
|
||||||
m_assignment.push_back(false);
|
m_assignment.push_back(false);
|
||||||
m_expr2var.insert(f, var);
|
m_expr2var.insert(f, var);
|
||||||
m_var2expr.push_back(f);
|
m_var2expr.push_back(f);
|
||||||
|
@ -146,6 +311,7 @@ namespace smt {
|
||||||
SASSERT(coeff.is_int());
|
SASSERT(coeff.is_int());
|
||||||
lit = mk_literal(args[i]);
|
lit = mk_literal(args[i]);
|
||||||
if (lit == null_literal) return false;
|
if (lit == null_literal) return false;
|
||||||
|
SASSERT(lit != false_literal && lit != true_literal);
|
||||||
cls.m_lits.push_back(lit);
|
cls.m_lits.push_back(lit);
|
||||||
cls.m_weights.push_back(coeff.to_mpq().numerator());
|
cls.m_weights.push_back(coeff.to_mpq().numerator());
|
||||||
if (get_value(lit)) {
|
if (get_value(lit)) {
|
||||||
|
@ -161,6 +327,7 @@ namespace smt {
|
||||||
for (unsigned i = 0; i < sz; ++i) {
|
for (unsigned i = 0; i < sz; ++i) {
|
||||||
lit = mk_literal(args[i]);
|
lit = mk_literal(args[i]);
|
||||||
if (lit == null_literal) return false;
|
if (lit == null_literal) return false;
|
||||||
|
SASSERT(lit != false_literal && lit != true_literal);
|
||||||
cls.m_lits.push_back(lit);
|
cls.m_lits.push_back(lit);
|
||||||
cls.m_weights.push_back(mpz(1));
|
cls.m_weights.push_back(mpz(1));
|
||||||
if (get_value(lit)) {
|
if (get_value(lit)) {
|
||||||
|
@ -173,6 +340,7 @@ namespace smt {
|
||||||
else {
|
else {
|
||||||
lit = mk_literal(f);
|
lit = mk_literal(f);
|
||||||
if (lit == null_literal) return false;
|
if (lit == null_literal) return false;
|
||||||
|
SASSERT(lit != false_literal && lit != true_literal);
|
||||||
cls.m_lits.push_back(lit);
|
cls.m_lits.push_back(lit);
|
||||||
cls.m_weights.push_back(mpz(1));
|
cls.m_weights.push_back(mpz(1));
|
||||||
cls.m_eq = true;
|
cls.m_eq = true;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue