3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-04-22 16:45:31 +00:00

working on card extension

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-01-30 17:22:06 -08:00
parent 92e2d920fd
commit 32b5e54c8d
2 changed files with 204 additions and 70 deletions

View file

@ -50,7 +50,7 @@ namespace sat {
if (c.lit().sign() == is_true) {
c.negate();
}
SASSERT(s().value(c.lit()) == l_true);
SASSERT(value(c.lit()) == l_true);
unsigned j = 0, sz = c.size(), bound = c.k();
if (bound == sz) {
for (unsigned i = 0; i < sz && !s().inconsistent(); ++i) {
@ -60,7 +60,7 @@ namespace sat {
}
// put the non-false literals into the head.
for (unsigned i = 0; i < sz; ++i) {
if (s().value(c[i]) != l_false) {
if (value(c[i]) != l_false) {
if (j != i) {
c.swap(i, j);
}
@ -70,8 +70,8 @@ namespace sat {
DEBUG_CODE(
bool is_false = false;
for (unsigned k = 0; k < sz; ++k) {
SASSERT(!is_false || s().value(c[k]) == l_false);
is_false = s().value(c[k]) == l_false;
SASSERT(!is_false || value(c[k]) == l_false);
is_false = value(c[k]) == l_false;
});
// j is the number of non-false, sz - j the number of false.
@ -86,7 +86,7 @@ namespace sat {
//
for (unsigned i = bound; i < sz; ++i) {
if (s().lvl(alit) < s().lvl(c[i])) {
if (lvl(alit) < lvl(c[i])) {
c.swap(i, j);
alit = c[j];
}
@ -133,7 +133,7 @@ namespace sat {
}
void card_extension::assign(card& c, literal lit) {
if (s().value(lit) == l_true) {
if (value(lit) == l_true) {
return;
}
m_stats.m_num_propagations++;
@ -155,19 +155,20 @@ namespace sat {
void card_extension::set_conflict(card& c, literal lit) {
SASSERT(validate_conflict(c));
literal_vector& lits = get_literals();
SASSERT(s().value(lit) == l_false);
SASSERT(s().value(c.lit()) == l_true);
lits.push_back(~c.lit());
lits.push_back(lit);
unsigned sz = c.size();
for (unsigned i = c.k(); i < sz; ++i) {
SASSERT(s().value(c[i]) == l_false);
lits.push_back(c[i]);
}
m_stats.m_num_conflicts++;
if (!resolve_conflict(c, lits)) {
if (!resolve_conflict(c, lit)) {
literal_vector& lits = get_literals();
SASSERT(value(lit) == l_false);
SASSERT(value(c.lit()) == l_true);
lits.push_back(~c.lit());
lits.push_back(lit);
unsigned sz = c.size();
for (unsigned i = c.k(); i < sz; ++i) {
SASSERT(value(c[i]) == l_false);
lits.push_back(c[i]);
}
s().mk_clause_core(lits.size(), lits.c_ptr(), true);
}
SASSERT(s().inconsistent());
@ -231,16 +232,16 @@ namespace sat {
m_active_vars.reset();
}
bool card_extension::resolve_conflict(card& c, literal_vector const& conflict_clause) {
bool card_extension::resolve_conflict(card& c, literal alit) {
bool_var v;
m_conflict_lvl = 0;
for (unsigned i = 0; i < c.size(); ++i) {
literal lit = c[i];
SASSERT(s().value(lit) == l_false);
m_conflict_lvl = std::max(m_conflict_lvl, s().lvl(lit));
SASSERT(value(lit) == l_false);
m_conflict_lvl = std::max(m_conflict_lvl, lvl(lit));
}
if (m_conflict_lvl < s().lvl(c.lit()) || m_conflict_lvl == 0) {
if (m_conflict_lvl < lvl(c.lit()) || m_conflict_lvl == 0) {
return false;
}
@ -251,14 +252,14 @@ namespace sat {
literal_vector const& lits = s().m_trail;
unsigned idx = lits.size()-1;
justification js;
literal consequent = ~conflict_clause[1];
literal consequent = ~alit;
process_card(c, 1);
literal alit;
DEBUG_CODE(active2pb(m_A););
while (m_num_marks > 0) {
SASSERT(value(consequent) == l_true);
v = consequent.var();
int offset = get_abs_coeff(v);
if (offset == 0) {
@ -268,9 +269,11 @@ namespace sat {
goto bail_out;
}
SASSERT(validate_lemma());
SASSERT(offset > 0);
js = s().m_justification[v];
DEBUG_CODE(justification2pb(js, consequent, offset, m_B););
int bound = 1;
switch(js.get_kind()) {
@ -289,15 +292,13 @@ namespace sat {
inc_coeff(consequent, offset);
clause & c = *(s().m_cls_allocator.get_clause(js.get_clause_offset()));
unsigned i = 0;
if (consequent != null_literal) {
SASSERT(c[0] == consequent || c[1] == consequent);
if (c[0] == consequent) {
i = 1;
}
else {
process_antecedent(~c[0], offset);
i = 2;
}
SASSERT(c[0] == consequent || c[1] == consequent);
if (c[0] == consequent) {
i = 1;
}
else {
process_antecedent(~c[0], offset);
i = 2;
}
unsigned sz = c.size();
for (; i < sz; i++)
@ -316,6 +317,11 @@ namespace sat {
break;
}
m_bound += offset * bound;
DEBUG_CODE(
active2pb(m_C);
SASSERT(validate_resolvent());
m_A = m_C;);
// cut();
@ -331,7 +337,7 @@ namespace sat {
--idx;
}
SASSERT(s().lvl(v) == m_conflict_lvl);
SASSERT(lvl(v) == m_conflict_lvl);
s().reset_mark(v);
--idx;
--m_num_marks;
@ -390,24 +396,24 @@ namespace sat {
void card_extension::process_card(card& c, int offset) {
SASSERT(c.k() <= c.size());
SASSERT(s().value(c.lit()) == l_true);
SASSERT(value(c.lit()) == l_true);
for (unsigned i = c.k(); i < c.size(); ++i) {
process_antecedent(c[i], offset);
}
for (unsigned i = 0; i < c.k(); ++i) {
inc_coeff(c[i], offset);
}
if (s().lvl(c.lit()) > 0) {
if (lvl(c.lit()) > 0) {
m_conflict.push_back(~c.lit());
}
}
void card_extension::process_antecedent(literal l, int offset) {
SASSERT(s().value(l) == l_false);
SASSERT(value(l) == l_false);
bool_var v = l.var();
unsigned lvl = s().lvl(v);
unsigned level = lvl(v);
if (lvl > 0 && !s().is_marked(v) && lvl == m_conflict_lvl) {
if (level > 0 && !s().is_marked(v) && level == m_conflict_lvl) {
s().mark(v);
++m_num_marks;
}
@ -418,12 +424,13 @@ namespace sat {
if (get_abs_coeff(p.var()) != 0) {
return p;
}
unsigned lvl = 0;
unsigned level = 0;
for (unsigned i = 0; i < m_active_vars.size(); ++i) {
bool_var v = m_active_vars[i];
literal lit(v, get_coeff(v) < 0);
if (s().value(lit) == l_false && s().lvl(lit) > lvl) {
if (value(lit) == l_false && lvl(lit) > level) {
p = lit;
level = lvl(lit);
}
}
return p;
@ -463,21 +470,24 @@ namespace sat {
}
SASSERT(found););
r.push_back(c.lit());
SASSERT(value(c.lit()) == l_true);
for (unsigned i = c.k(); i < c.size(); ++i) {
SASSERT(s().value(c[i]) == l_false);
r.push_back(c[i]);
SASSERT(value(c[i]) == l_false);
r.push_back(~c[i]);
}
}
lbool card_extension::add_assign(card& c, literal alit) {
// literal is assigned to false.
unsigned sz = c.size();
unsigned bound = c.k();
TRACE("pb", tout << "assign: " << c.lit() << " " << ~alit << " " << bound << "\n";);
TRACE("sat", tout << "assign: " << c.lit() << " " << ~alit << " " << bound << "\n";);
SASSERT(0 < bound && bound < sz);
SASSERT(s().value(alit) == l_false);
SASSERT(s().value(c.lit()) == l_true);
SASSERT(value(alit) == l_false);
SASSERT(value(c.lit()) == l_true);
unsigned index = 0;
for (index = 0; index <= bound; ++index) {
if (c[index] == alit) {
@ -494,7 +504,7 @@ namespace sat {
// find a literal to swap with:
for (unsigned i = bound + 1; i < sz; ++i) {
literal lit2 = c[i];
if (s().value(lit2) != l_false) {
if (value(lit2) != l_false) {
c.swap(index, i);
watch_literal(c, lit2);
return l_undef;
@ -502,13 +512,13 @@ namespace sat {
}
// conflict
if (bound != index && s().value(c[bound]) == l_false) {
if (bound != index && value(c[bound]) == l_false) {
TRACE("sat", tout << "conflict " << c[bound] << " " << alit << "\n";);
set_conflict(c, alit);
return l_false;
}
TRACE("pb", tout << "no swap " << index << " " << alit << "\n";);
TRACE("sat", tout << "no swap " << index << " " << alit << "\n";);
// there are no literals to swap with,
// prepare for unit propagation by swapping the false literal into
// position bound. Then literals in positions 0..bound-1 have to be
@ -532,7 +542,7 @@ namespace sat {
ptr_vector<card>::iterator it = cards->begin(), it2 = it, end = cards->end();
for (; it != end; ++it) {
card& c = *(*it);
if (s().value(c.lit()) != l_true) {
if (value(c.lit()) != l_true) {
continue;
}
switch (add_assign(c, l)) {
@ -604,9 +614,9 @@ namespace sat {
out << c.lit();
if (c.lit() != null_literal) {
if (values) {
out << "@(" << s().value(c.lit());
if (s().value(c.lit()) != l_undef) {
out << ":" << s().lvl(c.lit());
out << "@(" << value(c.lit());
if (value(c.lit()) != l_undef) {
out << ":" << lvl(c.lit());
}
out << ")";
}
@ -619,9 +629,9 @@ namespace sat {
literal l = c[i];
out << l;
if (values) {
out << "@(" << s().value(l);
if (s().value(l) != l_undef) {
out << ":" << s().lvl(l);
out << "@(" << value(l);
if (value(l) != l_undef) {
out << ":" << lvl(l);
}
out << ") ";
}
@ -651,35 +661,142 @@ namespace sat {
bool card_extension::validate_conflict(card& c) {
if (!validate_unit_propagation(c)) return false;
for (unsigned i = 0; i < c.k(); ++i) {
if (s().value(c[i]) == l_false) return true;
if (value(c[i]) == l_false) return true;
}
return false;
}
bool card_extension::validate_unit_propagation(card const& c) {
if (value(c.lit()) != l_true) return false;
for (unsigned i = c.k(); i < c.size(); ++i) {
if (s().value(c[i]) != l_false) return false;
if (value(c[i]) != l_false) return false;
}
return true;
}
bool card_extension::validate_lemma() {
int value = -m_bound;
int val = -m_bound;
normalize_active_coeffs();
for (unsigned i = 0; i < m_active_vars.size(); ++i) {
bool_var v = m_active_vars[i];
int coeff = get_coeff(v);
literal lit(v, false);
SASSERT(coeff != 0);
if (coeff < 0 && s().value(v) != l_true) {
value -= coeff;
if (coeff < 0 && value(lit) != l_true) {
val -= coeff;
}
else if (coeff > 0 && s().value(v) != l_false) {
value += coeff;
else if (coeff > 0 && value(lit) != l_false) {
val += coeff;
}
}
return value < 0;
return val < 0;
}
bool card_extension::validate_assign(literal_vector const& lits, literal lit) { return true; }
bool card_extension::validate_conflict(literal_vector const& lits) { return true; }
void card_extension::active2pb(ineq& p) {
normalize_active_coeffs();
p.reset(m_bound);
for (unsigned i = 0; i < m_active_vars.size(); ++i) {
bool_var v = m_active_vars[i];
literal lit(v, get_coeff(v) < 0);
p.m_lits.push_back(lit);
p.m_coeffs.push_back(get_abs_coeff(v));
}
}
void card_extension::justification2pb(justification const& js, literal lit, unsigned offset, ineq& p) {
switch (js.get_kind()) {
case justification::NONE:
p.reset(0);
break;
case justification::BINARY:
p.reset(offset);
p.push(lit, offset);
p.push(~js.get_literal(), offset);
break;
case justification::TERNARY:
p.reset(offset);
p.push(lit, offset);
p.push(~(js.get_literal1()), offset);
p.push(~(js.get_literal2()), offset);
break;
case justification::CLAUSE: {
p.reset(offset);
clause & c = *(s().m_cls_allocator.get_clause(js.get_clause_offset()));
unsigned sz = c.size();
for (unsigned i = 0; i < sz; i++)
p.push(~c[i], offset);
break;
}
case justification::EXT_JUSTIFICATION: {
unsigned index = js.get_ext_justification_idx();
card& c = *m_constraints[index];
p.reset(offset*c.k());
for (unsigned i = 0; i < c.size(); ++i) {
p.push(c[i], offset);
}
break;
}
default:
UNREACHABLE();
break;
}
}
// validate that m_A & m_B implies m_C
bool card_extension::validate_resolvent() {
u_map<unsigned> coeffs;
unsigned k = m_A.m_k + m_B.m_k;
for (unsigned i = 0; i < m_A.m_lits.size(); ++i) {
unsigned coeff = m_A.m_coeffs[i];
SASSERT(!coeffs.contains(m_A.m_lits[i].index()));
coeffs.insert(m_A.m_lits[i].index(), coeff);
}
for (unsigned i = 0; i < m_B.m_lits.size(); ++i) {
unsigned coeff1 = m_B.m_coeffs[i], coeff2;
literal lit = m_B.m_lits[i];
if (coeffs.find((~lit).index(), coeff2)) {
if (coeff1 == coeff2) {
coeffs.remove((~lit).index());
k += coeff1;
}
else if (coeff1 < coeff2) {
coeffs.insert((~lit).index(), coeff2 - coeff1);
k += coeff1;
}
else {
SASSERT(coeff2 < coeff1);
coeffs.remove((~lit).index());
coeffs.insert(lit.index(), coeff1 - coeff2);
k += coeff2;
}
}
else if (coeffs.find(lit.index(), coeff2)) {
coeffs.insert(lit.index(), coeff1 + coeff2);
}
else {
coeffs.insert(lit.index(), coeff1);
}
}
// C is above the sum of A and B
for (unsigned i = 0; i < m_C.m_lits.size(); ++i) {
literal lit = m_C.m_lits[i];
unsigned coeff;
if (coeffs.find(lit.index(), coeff)) {
SASSERT(coeff <= m_C.m_coeffs[i]);
coeffs.remove(lit.index());
}
}
SASSERT(coeffs.empty());
SASSERT(m_C.m_k <= k);
return true;
}
bool card_extension::validate_conflict(literal_vector const& lits) {
for (unsigned i = 0; i < lits.size(); ++i) {
if (value(lits[i]) != l_false) return false;
}
return true;
}
};

View file

@ -23,7 +23,7 @@ Revision History:
#include"sat_solver.h"
namespace sat {
class card_extension : public extension {
struct stats {
unsigned m_num_propagations;
@ -31,7 +31,7 @@ namespace sat {
stats() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); }
};
class card {
unsigned m_index;
literal m_lit;
@ -49,6 +49,14 @@ namespace sat {
void negate();
};
struct ineq {
literal_vector m_lits;
unsigned_vector m_coeffs;
unsigned m_k;
void reset(unsigned k) { m_lits.reset(); m_coeffs.reset(); m_k = k; }
void push(literal l, unsigned c) { m_lits.push_back(l); m_coeffs.push_back(c); }
};
typedef ptr_vector<card> watch;
struct var_info {
watch* m_lit_watch[2];
@ -95,6 +103,10 @@ namespace sat {
void clear_watch(card& c);
void reset_coeffs();
inline lbool value(literal lit) const { return m_solver->value(lit); }
inline unsigned lvl(literal lit) const { return m_solver->lvl(lit); }
inline unsigned lvl(bool_var v) const { return m_solver->lvl(v); }
void unwatch_literal(literal w, card* c);
void remove(ptr_vector<card>& cards, card* c);
@ -105,7 +117,7 @@ namespace sat {
literal_vector& get_literals() { m_literals.reset(); return m_literals; }
literal get_asserting_literal(literal conseq);
bool resolve_conflict(card& c, literal_vector const& conflict_clause);
bool resolve_conflict(card& c, literal alit);
void process_antecedent(literal l, int offset);
void process_card(card& c, int offset);
void cut();
@ -117,6 +129,11 @@ namespace sat {
bool validate_unit_propagation(card const& c);
bool validate_conflict(literal_vector const& lits);
ineq m_A, m_B, m_C;
void active2pb(ineq& p);
void justification2pb(justification const& j, literal lit, unsigned offset, ineq& p);
bool validate_resolvent();
void display(std::ostream& out, card& c, bool values) const;
void display_watch(std::ostream& out, bool_var v, bool sign) const;
public: