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

working on card for sat

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2017-01-30 14:03:27 -08:00
parent a412a554eb
commit 92e2d920fd
8 changed files with 839 additions and 12 deletions

View file

@ -1,5 +1,6 @@
z3_add_component(sat
SOURCES
card_extension.cpp
dimacs.cpp
sat_asymm_branch.cpp
sat_clause.cpp

686
src/sat/card_extension.cpp Normal file
View file

@ -0,0 +1,686 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
card_extension.cpp
Abstract:
Extension for cardinality reasoning.
Author:
Nikolaj Bjorner (nbjorner) 2017-01-30
Revision History:
--*/
#include"card_extension.h"
#include"sat_types.h"
namespace sat {
card_extension::card::card(unsigned index, literal lit, literal_vector const& lits, unsigned k):
m_index(index),
m_lit(lit),
m_k(k),
m_size(lits.size()),
m_lits(lits) {
}
void card_extension::card::negate() {
m_lit.neg();
for (unsigned i = 0; i < m_size; ++i) {
m_lits[i].neg();
}
m_k = m_size - m_k + 1;
SASSERT(m_size >= m_k && m_k > 0);
}
void card_extension::init_watch(bool_var v) {
if (m_var_infos.size() <= static_cast<unsigned>(v)) {
m_var_infos.resize(static_cast<unsigned>(v)+100);
}
}
void card_extension::init_watch(card& c, bool is_true) {
clear_watch(c);
if (c.lit().sign() == is_true) {
c.negate();
}
SASSERT(s().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) {
assign(c, c[i]);
}
return;
}
// put the non-false literals into the head.
for (unsigned i = 0; i < sz; ++i) {
if (s().value(c[i]) != l_false) {
if (j != i) {
c.swap(i, j);
}
++j;
}
}
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;
});
// j is the number of non-false, sz - j the number of false.
if (j < bound) {
SASSERT(0 < bound && bound < sz);
literal alit = c[j];
//
// we need the assignment level of the asserting literal to be maximal.
// such that conflict resolution can use the asserting literal as a starting
// point.
//
for (unsigned i = bound; i < sz; ++i) {
if (s().lvl(alit) < s().lvl(c[i])) {
c.swap(i, j);
alit = c[j];
}
}
set_conflict(c, alit);
}
else if (j == bound) {
for (unsigned i = 0; i < bound && !s().inconsistent(); ++i) {
assign(c, c[i]);
}
}
else {
for (unsigned i = 0; i <= bound; ++i) {
watch_literal(c, c[i]);
}
}
}
void card_extension::clear_watch(card& c) {
unsigned sz = std::min(c.k() + 1, c.size());
for (unsigned i = 0; i < sz; ++i) {
unwatch_literal(c[i], &c);
}
}
void card_extension::unwatch_literal(literal lit, card* c) {
if (m_var_infos.size() <= static_cast<unsigned>(lit.var())) {
return;
}
ptr_vector<card>* cards = m_var_infos[lit.var()].m_lit_watch[lit.sign()];
if (cards) {
remove(*cards, c);
}
}
void card_extension::remove(ptr_vector<card>& cards, card* c) {
for (unsigned j = 0; j < cards.size(); ++j) {
if (cards[j] == c) {
std::swap(cards[j], cards[cards.size()-1]);
cards.pop_back();
break;
}
}
}
void card_extension::assign(card& c, literal lit) {
if (s().value(lit) == l_true) {
return;
}
m_stats.m_num_propagations++;
//TRACE("sat", tout << "#prop: " << m_stats.m_num_propagations << " - " << c.lit() << " => " << lit << "\n";);
SASSERT(validate_unit_propagation(c));
s().assign(lit, justification::mk_ext_justification(c.index()));
}
void card_extension::watch_literal(card& c, literal lit) {
init_watch(lit.var());
ptr_vector<card>* cards = m_var_infos[lit.var()].m_lit_watch[lit.sign()];
if (cards == 0) {
cards = alloc(ptr_vector<card>);
m_var_infos[lit.var()].m_lit_watch[lit.sign()] = cards;
}
cards->push_back(&c);
}
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)) {
s().mk_clause_core(lits.size(), lits.c_ptr(), true);
}
SASSERT(s().inconsistent());
}
void card_extension::normalize_active_coeffs() {
while (!m_active_var_set.empty()) m_active_var_set.erase();
unsigned i = 0, j = 0, sz = m_active_vars.size();
for (; i < sz; ++i) {
bool_var v = m_active_vars[i];
if (!m_active_var_set.contains(v) && get_coeff(v) != 0) {
m_active_var_set.insert(v);
if (j != i) {
m_active_vars[j] = m_active_vars[i];
}
++j;
}
}
sz = j;
m_active_vars.shrink(sz);
}
void card_extension::inc_coeff(literal l, int offset) {
SASSERT(offset > 0);
bool_var v = l.var();
SASSERT(v != null_bool_var);
if (static_cast<bool_var>(m_coeffs.size()) <= v) {
m_coeffs.resize(v + 1, 0);
}
int coeff0 = m_coeffs[v];
if (coeff0 == 0) {
m_active_vars.push_back(v);
}
int inc = l.sign() ? -offset : offset;
int coeff1 = inc + coeff0;
m_coeffs[v] = coeff1;
if (coeff0 > 0 && inc < 0) {
m_bound -= coeff0 - std::max(0, coeff1);
}
else if (coeff0 < 0 && inc > 0) {
m_bound -= std::min(0, coeff1) - coeff0;
}
}
int card_extension::get_coeff(bool_var v) const {
return m_coeffs.get(v, 0);
}
int card_extension::get_abs_coeff(bool_var v) const {
int coeff = get_coeff(v);
if (coeff < 0) coeff = -coeff;
return coeff;
}
void card_extension::reset_coeffs() {
for (unsigned i = 0; i < m_active_vars.size(); ++i) {
m_coeffs[m_active_vars[i]] = 0;
}
m_active_vars.reset();
}
bool card_extension::resolve_conflict(card& c, literal_vector const& conflict_clause) {
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));
}
if (m_conflict_lvl < s().lvl(c.lit()) || m_conflict_lvl == 0) {
return false;
}
reset_coeffs();
m_num_marks = 0;
m_bound = c.k();
m_conflict.reset();
literal_vector const& lits = s().m_trail;
unsigned idx = lits.size()-1;
justification js;
literal consequent = ~conflict_clause[1];
process_card(c, 1);
literal alit;
while (m_num_marks > 0) {
v = consequent.var();
int offset = get_abs_coeff(v);
if (offset == 0) {
goto process_next_resolvent;
}
if (offset > 1000) {
goto bail_out;
}
SASSERT(offset > 0);
js = s().m_justification[v];
int bound = 1;
switch(js.get_kind()) {
case justification::NONE:
break;
case justification::BINARY:
inc_coeff(consequent, offset);
process_antecedent(~(js.get_literal()), offset);
break;
case justification::TERNARY:
inc_coeff(consequent, offset);
process_antecedent(~(js.get_literal1()), offset);
process_antecedent(~(js.get_literal2()), offset);
break;
case justification::CLAUSE: {
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;
}
}
unsigned sz = c.size();
for (; i < sz; i++)
process_antecedent(~c[i], offset);
break;
}
case justification::EXT_JUSTIFICATION: {
unsigned index = js.get_ext_justification_idx();
card& c2 = *m_constraints[index];
process_card(c2, offset);
bound = c2.k();
break;
}
default:
UNREACHABLE();
break;
}
m_bound += offset * bound;
// cut();
process_next_resolvent:
// find the next marked variable in the assignment stack
//
while (true) {
consequent = lits[idx];
v = consequent.var();
if (s().is_marked(v)) break;
SASSERT(idx > 0);
--idx;
}
SASSERT(s().lvl(v) == m_conflict_lvl);
s().reset_mark(v);
--idx;
--m_num_marks;
}
SASSERT(validate_lemma());
normalize_active_coeffs();
if (m_bound > 0 && m_active_vars.empty()) {
return false;
}
int slack = -m_bound;
for (unsigned i = 0; i < m_active_vars.size(); ++i) {
bool_var v = m_active_vars[i];
slack += get_abs_coeff(v);
}
alit = get_asserting_literal(~consequent);
slack -= get_abs_coeff(alit.var());
m_conflict.push_back(alit);
for (unsigned i = lits.size(); 0 <= slack && i > 0; ) {
--i;
literal lit = lits[i];
bool_var v = lit.var();
if (m_active_var_set.contains(v) && v != alit.var()) {
int coeff = get_coeff(v);
if (coeff < 0 && !lit.sign()) {
slack += coeff;
m_conflict.push_back(~lit);
}
else if (coeff > 0 && lit.sign()) {
slack -= coeff;
m_conflict.push_back(~lit);
}
}
}
SASSERT(slack < 0);
SASSERT(validate_conflict(m_conflict));
s().mk_clause_core(m_conflict.size(), m_conflict.c_ptr(), true);
return true;
bail_out:
while (m_num_marks > 0 && idx > 0) {
v = lits[idx].var();
if (s().is_marked(v)) {
s().reset_mark(v);
}
--idx;
}
return false;
}
void card_extension::process_card(card& c, int offset) {
SASSERT(c.k() <= c.size());
SASSERT(s().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) {
m_conflict.push_back(~c.lit());
}
}
void card_extension::process_antecedent(literal l, int offset) {
SASSERT(s().value(l) == l_false);
bool_var v = l.var();
unsigned lvl = s().lvl(v);
if (lvl > 0 && !s().is_marked(v) && lvl == m_conflict_lvl) {
s().mark(v);
++m_num_marks;
}
inc_coeff(l, offset);
}
literal card_extension::get_asserting_literal(literal p) {
if (get_abs_coeff(p.var()) != 0) {
return p;
}
unsigned lvl = 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) {
p = lit;
}
}
return p;
}
card_extension::card_extension(): m_solver(0) {}
card_extension::~card_extension() {
for (unsigned i = 0; i < m_var_infos.size(); ++i) {
m_var_infos[i].reset();
}
m_var_trail.reset();
m_var_lim.reset();
m_stats.reset();
}
void card_extension::add_at_least(bool_var v, literal_vector const& lits, unsigned k) {
unsigned index = m_constraints.size();
card* c = alloc(card, index, literal(v, false), lits, k);
m_constraints.push_back(c);
init_watch(v);
m_var_infos[v].m_card = c;
m_var_trail.push_back(v);
}
void card_extension::propagate(literal l, ext_constraint_idx idx, bool & keep) {
UNREACHABLE();
}
void card_extension::get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) {
card& c = *m_constraints[idx];
DEBUG_CODE(
bool found = false;
for (unsigned i = 0; !found && i < c.k(); ++i) {
found = c[i] == l;
}
SASSERT(found););
for (unsigned i = c.k(); i < c.size(); ++i) {
SASSERT(s().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";);
SASSERT(0 < bound && bound < sz);
SASSERT(s().value(alit) == l_false);
SASSERT(s().value(c.lit()) == l_true);
unsigned index = 0;
for (index = 0; index <= bound; ++index) {
if (c[index] == alit) {
break;
}
}
if (index == bound + 1) {
// literal is no longer watched.
return l_undef;
}
SASSERT(index <= bound);
SASSERT(c[index] == alit);
// find a literal to swap with:
for (unsigned i = bound + 1; i < sz; ++i) {
literal lit2 = c[i];
if (s().value(lit2) != l_false) {
c.swap(index, i);
watch_literal(c, lit2);
return l_undef;
}
}
// conflict
if (bound != index && s().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";);
// 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
// assigned l_true.
if (index != bound) {
c.swap(index, bound);
}
SASSERT(validate_unit_propagation(c));
for (unsigned i = 0; i < bound && !s().inconsistent(); ++i) {
assign(c, c[i]);
}
return s().inconsistent() ? l_false : l_true;
}
void card_extension::asserted(literal l) {
bool_var v = l.var();
ptr_vector<card>* cards = m_var_infos[v].m_lit_watch[!l.sign()];
if (cards != 0 && !cards->empty() && !s().inconsistent()) {
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) {
continue;
}
switch (add_assign(c, l)) {
case l_false: // conflict
for (; it != end; ++it, ++it2) {
*it2 = *it;
}
SASSERT(s().inconsistent());
cards->set_end(it2);
return;
case l_undef: // watch literal was swapped
break;
case l_true: // unit propagation, keep watching the literal
if (it2 != it) {
*it2 = *it;
}
++it2;
break;
}
}
cards->set_end(it2);
}
card* crd = m_var_infos[v].m_card;
if (crd != 0 && !s().inconsistent()) {
init_watch(*crd, !l.sign());
}
}
check_result card_extension::check() { return CR_DONE; }
void card_extension::push() {
m_var_lim.push_back(m_var_trail.size());
}
void card_extension::pop(unsigned n) {
unsigned new_lim = m_var_lim.size() - n;
unsigned sz = m_var_lim[new_lim];
while (m_var_trail.size() > sz) {
bool_var v = m_var_trail.back();
m_var_trail.pop_back();
if (v != null_bool_var) {
card* c = m_var_infos[v].m_card;
clear_watch(*c);
m_var_infos[v].m_card = 0;
dealloc(c);
}
}
m_var_lim.resize(new_lim);
}
void card_extension::simplify() {}
void card_extension::clauses_modifed() {}
lbool card_extension::get_phase(bool_var v) { return l_undef; }
void card_extension::display_watch(std::ostream& out, bool_var v, bool sign) const {
watch const* w = m_var_infos[v].m_lit_watch[sign];
if (w) {
watch const& wl = *w;
out << "watch: " << literal(v, sign) << " |-> ";
for (unsigned i = 0; i < wl.size(); ++i) {
out << wl[i]->lit() << " ";
}
out << "\n";
}
}
void card_extension::display(std::ostream& out, card& c, bool values) const {
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 << ")";
}
out << c.lit() << "\n";
}
else {
out << " ";
}
for (unsigned i = 0; i < c.size(); ++i) {
literal l = c[i];
out << l;
if (values) {
out << "@(" << s().value(l);
if (s().value(l) != l_undef) {
out << ":" << s().lvl(l);
}
out << ") ";
}
}
out << " >= " << c.k() << "\n";
}
std::ostream& card_extension::display(std::ostream& out) const {
for (unsigned vi = 0; vi < m_var_infos.size(); ++vi) {
display_watch(out, vi, false);
display_watch(out, vi, true);
}
for (unsigned vi = 0; vi < m_var_infos.size(); ++vi) {
card* c = m_var_infos[vi].m_card;
if (c) {
display(out, *c, true);
}
}
return out;
}
void card_extension::collect_statistics(statistics& st) const {
st.update("card propagations", m_stats.m_num_propagations);
st.update("card conflicts", m_stats.m_num_conflicts);
}
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;
}
return false;
}
bool card_extension::validate_unit_propagation(card const& c) {
for (unsigned i = c.k(); i < c.size(); ++i) {
if (s().value(c[i]) != l_false) return false;
}
return true;
}
bool card_extension::validate_lemma() {
int value = -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);
SASSERT(coeff != 0);
if (coeff < 0 && s().value(v) != l_true) {
value -= coeff;
}
else if (coeff > 0 && s().value(v) != l_false) {
value += coeff;
}
}
return value < 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; }
};

142
src/sat/card_extension.h Normal file
View file

@ -0,0 +1,142 @@
/*++
Copyright (c) 2017 Microsoft Corporation
Module Name:
card_extension.h
Abstract:
Cardinality extensions.
Author:
Nikolaj Bjorner (nbjorner) 2017-01-30
Revision History:
--*/
#ifndef CARD_EXTENSION_H_
#define CARD_EXTENSION_H_
#include"sat_extension.h"
#include"sat_solver.h"
namespace sat {
class card_extension : public extension {
struct stats {
unsigned m_num_propagations;
unsigned m_num_conflicts;
stats() { reset(); }
void reset() { memset(this, 0, sizeof(*this)); }
};
class card {
unsigned m_index;
literal m_lit;
unsigned m_k;
unsigned m_size;
literal_vector m_lits;
public:
card(unsigned index, literal lit, literal_vector const& lits, unsigned k);
unsigned index() const { return m_index; }
literal lit() const { return m_lit; }
literal operator[](unsigned i) const { return m_lits[i]; }
unsigned k() const { return m_k; }
unsigned size() const { return m_size; }
void swap(unsigned i, unsigned j) { std::swap(m_lits[i], m_lits[j]); }
void negate();
};
typedef ptr_vector<card> watch;
struct var_info {
watch* m_lit_watch[2];
card* m_card;
var_info(): m_card(0) {
m_lit_watch[0] = 0;
m_lit_watch[1] = 0;
}
void reset() {
dealloc(m_card);
dealloc(m_lit_watch[0]);
dealloc(m_lit_watch[1]);
}
};
solver* m_solver;
stats m_stats;
ptr_vector<card> m_constraints;
// watch literals
svector<var_info> m_var_infos;
unsigned_vector m_var_trail;
unsigned_vector m_var_lim;
// conflict resolution
unsigned m_num_marks;
unsigned m_conflict_lvl;
svector<int> m_coeffs;
svector<bool_var> m_active_vars;
int m_bound;
tracked_uint_set m_active_var_set;
literal_vector m_conflict;
literal_vector m_literals;
solver& s() const { return *m_solver; }
void init_watch(card& c, bool is_true);
void init_watch(bool_var v);
void assign(card& c, literal lit);
lbool add_assign(card& c, literal lit);
void watch_literal(card& c, literal lit);
void set_conflict(card& c, literal lit);
void clear_watch(card& c);
void reset_coeffs();
void unwatch_literal(literal w, card* c);
void remove(ptr_vector<card>& cards, card* c);
void normalize_active_coeffs();
void inc_coeff(literal l, int offset);
int get_coeff(bool_var v) const;
int get_abs_coeff(bool_var v) const;
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);
void process_antecedent(literal l, int offset);
void process_card(card& c, int offset);
void cut();
// validation utilities
bool validate_conflict(card& c);
bool validate_assign(literal_vector const& lits, literal lit);
bool validate_lemma();
bool validate_unit_propagation(card const& c);
bool validate_conflict(literal_vector const& lits);
void display(std::ostream& out, card& c, bool values) const;
void display_watch(std::ostream& out, bool_var v, bool sign) const;
public:
card_extension();
virtual ~card_extension();
void set_solver(solver* s) { m_solver = s; }
void add_at_least(bool_var v, literal_vector const& lits, unsigned k);
virtual void propagate(literal l, ext_constraint_idx idx, bool & keep);
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r);
virtual void asserted(literal l);
virtual check_result check();
virtual void push();
virtual void pop(unsigned n);
virtual void simplify();
virtual void clauses_modifed();
virtual lbool get_phase(bool_var v);
virtual std::ostream& display(std::ostream& out) const;
virtual void collect_statistics(statistics& st) const;
};
};
#endif

View file

@ -21,6 +21,7 @@ Revision History:
#include"sat_types.h"
#include"params.h"
#include"statistics.h"
namespace sat {
@ -30,6 +31,7 @@ namespace sat {
class extension {
public:
virtual ~extension() {}
virtual void propagate(literal l, ext_constraint_idx idx, bool & keep) = 0;
virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) = 0;
virtual void asserted(literal l) = 0;
@ -39,6 +41,8 @@ namespace sat {
virtual void simplify() = 0;
virtual void clauses_modifed() = 0;
virtual lbool get_phase(bool_var v) = 0;
virtual std::ostream& display(std::ostream& out) const = 0;
virtual void collect_statistics(statistics& st) const = 0;
};
};

View file

@ -33,7 +33,7 @@ namespace sat {
explicit justification(literal l):m_val1(l.to_uint()), m_val2(BINARY) {}
justification(literal l1, literal l2):m_val1(l1.to_uint()), m_val2(TERNARY + (l2.to_uint() << 3)) {}
explicit justification(clause_offset cls_off):m_val1(cls_off), m_val2(CLAUSE) {}
justification mk_ext_justification(ext_justification_idx idx) { return justification(idx, EXT_JUSTIFICATION); }
static justification mk_ext_justification(ext_justification_idx idx) { return justification(idx, EXT_JUSTIFICATION); }
kind get_kind() const { return static_cast<kind>(m_val2 & 7); }

View file

@ -2752,6 +2752,7 @@ namespace sat {
m_scc.collect_statistics(st);
m_asymm_branch.collect_statistics(st);
m_probing.collect_statistics(st);
if (m_ext) m_ext->collect_statistics(st);
}
void solver::reset_statistics() {
@ -2856,6 +2857,9 @@ namespace sat {
display_units(out);
display_binary(out);
out << m_clauses << m_learned;
if (m_ext) {
m_ext->display(out);
}
out << ")\n";
}

View file

@ -145,6 +145,7 @@ namespace sat {
friend class probing;
friend class iff3_finder;
friend class mus;
friend class card_extension;
friend struct mk_stat;
public:
solver(params_ref const & p, reslimit& l, extension * ext);

View file

@ -250,16 +250,6 @@ namespace smt {
typedef map<arg_t, bool_var, arg_t::hash, arg_t::eq> arg_map;
struct row_info {
unsigned m_slack; // slack variable in simplex tableau
numeral m_bound; // bound
arg_t m_rep; // representative
row_info(theory_var slack, numeral const& b, arg_t const& r):
m_slack(slack), m_bound(b), m_rep(r) {}
row_info(): m_slack(0) {}
};
struct var_info {
ineq_watch* m_lit_watch[2];
ineq_watch* m_var_watch;
@ -290,7 +280,6 @@ namespace smt {
theory_pb_params m_params;
svector<var_info> m_var_infos;
unsynch_mpq_inf_manager m_mpq_inf_mgr; // Simplex: manage inf_mpq numerals
mutable unsynch_mpz_manager m_mpz_mgr; // Simplex: manager mpz numerals
unsigned_vector m_ineqs_trail;
unsigned_vector m_ineqs_lim;