3
0
Fork 0
mirror of https://github.com/Z3Prover/z3 synced 2025-06-06 22:23:22 +00:00

update hitting set implementation

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
Nikolaj Bjorner 2014-06-23 11:28:38 -07:00
parent 04407938be
commit 519c9dba25
2 changed files with 213 additions and 100 deletions

View file

@ -130,6 +130,7 @@ namespace simplex {
void simplex<Ext>::add_patch(var_t v) { void simplex<Ext>::add_patch(var_t v) {
SASSERT(is_base(v)); SASSERT(is_base(v));
if (outside_bounds(v)) { if (outside_bounds(v)) {
TRACE("simplex", tout << "Add patch: v" << v << "\n";);
m_to_patch.insert(v); m_to_patch.insert(v);
} }
} }
@ -200,12 +201,18 @@ namespace simplex {
var_info& vi = m_vars[var]; var_info& vi = m_vars[var];
em.set(vi.m_lower, b); em.set(vi.m_lower, b);
vi.m_lower_valid = true; vi.m_lower_valid = true;
TRACE("simplex", em.display(tout << "v" << var << " lower: ", b);
em.display(tout << " value: ", vi.m_value););
SASSERT(!vi.m_upper_valid || em.le(b, vi.m_upper)); SASSERT(!vi.m_upper_valid || em.le(b, vi.m_upper));
if (!vi.m_is_base && em.lt(vi.m_value, b)) { if (!vi.m_is_base && em.lt(vi.m_value, b)) {
scoped_eps_numeral delta(em); scoped_eps_numeral delta(em);
em.sub(b, vi.m_value, delta); em.sub(b, vi.m_value, delta);
update_value(var, delta); update_value(var, delta);
} }
else if (vi.m_is_base && em.lt(vi.m_value, b)) {
SASSERT(outside_bounds(var));
add_patch(var);
}
SASSERT(well_formed()); SASSERT(well_formed());
} }
@ -220,6 +227,10 @@ namespace simplex {
em.sub(b, vi.m_value, delta); em.sub(b, vi.m_value, delta);
update_value(var, delta); update_value(var, delta);
} }
else if (vi.m_is_base && em.lt(b, vi.m_value)) {
SASSERT(outside_bounds(var));
add_patch(var);
}
SASSERT(well_formed()); SASSERT(well_formed());
} }

View file

@ -30,7 +30,6 @@ typedef simplex::sparse_matrix<simplex::mpz_ext> sparse_matrix;
namespace opt { namespace opt {
struct hitting_sets::imp { struct hitting_sets::imp {
typedef unsigned_vector set;
class justification { class justification {
public: public:
enum kind_t { AXIOM, DECISION, CLAUSE }; enum kind_t { AXIOM, DECISION, CLAUSE };
@ -55,14 +54,49 @@ namespace opt {
kind_t kind() const { return m_kind; } kind_t kind() const { return m_kind; }
bool pos() const { return m_pos; } bool pos() const { return m_pos; }
}; };
class set {
unsigned m_num_elems;
unsigned m_elems[0];
set(): m_num_elems(0) {}
public:
static set* mk(small_object_allocator& alloc, unsigned sz, unsigned const* elems) {
unsigned size = (sz+1)*sizeof(unsigned);
void * mem = alloc.allocate(size);
set* result = new (mem) set();
result->m_num_elems = sz;
memcpy(result->m_elems, elems, sizeof(unsigned)*sz);
return result;
}
inline unsigned operator[](unsigned idx) const {
SASSERT(idx < m_num_elems);
return m_elems[idx];
}
inline unsigned& operator[](unsigned idx) {
SASSERT(idx < m_num_elems);
return m_elems[idx];
}
unsigned size() const { return m_num_elems; }
unsigned alloc_size() const { return (m_num_elems + 1)*sizeof(unsigned); }
bool empty() const { return 0 == size(); }
};
volatile bool m_cancel; volatile bool m_cancel;
rational m_lower; rational m_lower;
rational m_upper; rational m_upper;
vector<rational> m_weights; vector<rational> m_weights;
vector<rational> m_weights_inv;
rational m_max_weight; rational m_max_weight;
rational m_denominator; rational m_denominator;
vector<set> m_T; small_object_allocator m_alloc;
vector<set> m_F; ptr_vector<set> m_T;
ptr_vector<set> m_F;
svector<lbool> m_value; svector<lbool> m_value;
svector<lbool> m_model; svector<lbool> m_model;
vector<unsigned_vector> m_tuse_list; vector<unsigned_vector> m_tuse_list;
@ -82,6 +116,18 @@ namespace opt {
rational m_weight; // current weight of assignment. rational m_weight; // current weight of assignment.
unsigned_vector m_indices; unsigned_vector m_indices;
unsigned_vector m_scores; unsigned_vector m_scores;
vector<rational> m_scored_weights;
svector<bool> m_score_updated;
bool m_enable_simplex;
struct compare_scores {
imp* m_imp;
compare_scores(imp* i):m_imp(i) {}
bool operator()(int v1, int v2) const {
return m_imp->m_scored_weights[v1] > m_imp->m_scored_weights[v2];
}
};
compare_scores m_compare_scores;
heap<compare_scores> m_heap;
svector<bool> m_mark; svector<bool> m_mark;
struct scope { struct scope {
unsigned m_trail_lim; unsigned m_trail_lim;
@ -105,7 +151,11 @@ namespace opt {
m_qhead(0), m_qhead(0),
m_scope_lvl(0), m_scope_lvl(0),
m_conflict_j(justification(justification::AXIOM)), m_conflict_j(justification(justification::AXIOM)),
m_inconsistent(false) { m_inconsistent(false),
m_compare_scores(this),
m_heap(0, m_compare_scores) {
m_enable_simplex = true;
} }
~imp() {} ~imp() {}
@ -116,6 +166,7 @@ namespace opt {
m_simplex.set_lower(var, mpq_inf(mpq(0),mpq(0))); m_simplex.set_lower(var, mpq_inf(mpq(0),mpq(0)));
m_simplex.set_upper(var, mpq_inf(mpq(1),mpq(0))); m_simplex.set_upper(var, mpq_inf(mpq(1),mpq(0)));
m_weights.push_back(w); m_weights.push_back(w);
m_weights_inv.push_back(rational::one());
m_value.push_back(l_undef); m_value.push_back(l_undef);
m_justification.push_back(justification(justification::DECISION)); m_justification.push_back(justification(justification::DECISION));
m_tuse_list.push_back(unsigned_vector()); m_tuse_list.push_back(unsigned_vector());
@ -127,6 +178,8 @@ namespace opt {
m_model.push_back(l_undef); m_model.push_back(l_undef);
m_mark.push_back(false); m_mark.push_back(false);
m_scores.push_back(0); m_scores.push_back(0);
m_scored_weights.push_back(rational(0));
m_score_updated.push_back(true);
m_max_weight += w; m_max_weight += w;
} }
@ -142,7 +195,7 @@ namespace opt {
vector<unsigned_vector>& use_list = sign?m_fuse_list:m_tuse_list; vector<unsigned_vector>& use_list = sign?m_fuse_list:m_tuse_list;
lbool val = sign?l_false:l_true; lbool val = sign?l_false:l_true;
justification j(justification::AXIOM); justification j(justification::AXIOM);
vector<set>& Sets = sign?m_F:m_T; ptr_vector<set>& Sets = sign?m_F:m_T;
vector<unsigned_vector>& watch = sign?m_fwatch:m_twatch; vector<unsigned_vector>& watch = sign?m_fwatch:m_twatch;
init_weights(); init_weights();
if (sz == 0) { if (sz == 0) {
@ -162,26 +215,28 @@ namespace opt {
j = justification(clause_id, !sign); j = justification(clause_id, !sign);
watch[S[0]].push_back(clause_id); watch[S[0]].push_back(clause_id);
watch[S[1]].push_back(clause_id); watch[S[1]].push_back(clause_id);
Sets.push_back(unsigned_vector(sz, S)); Sets.push_back(set::mk(m_alloc, sz, S));
if (!sign) { if (!sign) {
pop(scope_lvl()); pop(scope_lvl());
inc_score(clause_id); inc_score(clause_id);
} }
TRACE("opt", display(tout, j);); TRACE("opt", display(tout, j););
// add_simplex_row(!sign, sz, S); if (!sign && m_enable_simplex) {
add_simplex_row(!sign, sz, S);
}
} }
return j; return j;
} }
lbool compute_lower() { lbool compute_lower() {
m_lower.reset(); m_lower.reset();
// L3() disabled: mostly a waste of time. rational w1 = L1();
if (L1() && L2()) { rational w2 = L2();
return l_true; rational w3 = L3();
} if (w1 > m_lower) m_lower = w1;
else { if (w2 > m_lower) m_lower = w2;
return l_undef; if (w3 > m_lower) m_lower = w3;
} return l_true;
} }
lbool compute_upper() { lbool compute_upper() {
@ -190,11 +245,14 @@ namespace opt {
lbool r = search(); lbool r = search();
pop(scope_lvl()); pop(scope_lvl());
std::cout << m_T.size() << " " << m_F.size() << "\n";
#if 0
// garbage collect agressively on exit. // garbage collect agressively on exit.
// all learned clases for negative branches are // all learned clases for negative branches are
// pruned. // pruned.
for (unsigned i = fsz; i < m_F.size(); ++i) {
m_alloc.deallocate(m_F[i]->alloc_size(), m_F[i]);
}
m_F.resize(fsz); m_F.resize(fsz);
for (unsigned i = 0; i < m_fuse_list.size(); ++i) { for (unsigned i = 0; i < m_fuse_list.size(); ++i) {
unsigned_vector & uses = m_fuse_list[i]; unsigned_vector & uses = m_fuse_list[i];
@ -209,6 +267,7 @@ namespace opt {
} }
watch.resize(k); watch.resize(k);
} }
#endif
return r; return r;
} }
@ -263,6 +322,20 @@ namespace opt {
m_weights[i] *= d; m_weights[i] *= d;
} }
} }
rational lc(1);
for (unsigned i = 0; i < m_weights.size(); ++i) {
lc = lcm(lc, m_weights[i]);
}
for (unsigned i = 0; i < m_weights.size(); ++i) {
m_weights_inv[i] = lc/m_weights[i];
}
m_heap.set_bounds(m_weights.size());
for (unsigned i = 0; i < m_weights.size(); ++i) {
m_heap.insert(i);
}
update_heap();
// set up Simplex objective function. // set up Simplex objective function.
for (unsigned i = 0; i < m_weights.size(); ++i) { for (unsigned i = 0; i < m_weights.size(); ++i) {
vars.push_back(i); vars.push_back(i);
@ -272,6 +345,7 @@ namespace opt {
vars.push_back(m_weights_var); vars.push_back(m_weights_var);
coeffs.push_back(mpz(-1)); coeffs.push_back(mpz(-1));
m_simplex.add_row(m_weights_var, coeffs.size(), vars.c_ptr(), coeffs.c_ptr()); m_simplex.add_row(m_weights_var, coeffs.size(), vars.c_ptr(), coeffs.c_ptr());
} }
void display(std::ostream& out) const { void display(std::ostream& out) const {
@ -281,10 +355,10 @@ namespace opt {
out << i << ": " << value(i) << " w: " << m_weights[i] << " s: " << m_scores[i] << "\n"; out << i << ": " << value(i) << " w: " << m_weights[i] << " s: " << m_scores[i] << "\n";
} }
for (unsigned i = 0; i < m_T.size(); ++i) { for (unsigned i = 0; i < m_T.size(); ++i) {
display(out << "+" << i << ": ", m_T[i]); display(out << "+" << i << ": ", *m_T[i]);
} }
for (unsigned i = 0; i < m_F.size(); ++i) { for (unsigned i = 0; i < m_F.size(); ++i) {
display(out << "-" << i << ": ", m_F[i]); display(out << "-" << i << ": ", *m_F[i]);
} }
out << "watch lists:\n"; out << "watch lists:\n";
for (unsigned i = 0; i < m_fwatch.size(); ++i) { for (unsigned i = 0; i < m_fwatch.size(); ++i) {
@ -321,7 +395,7 @@ namespace opt {
break; break;
case justification::CLAUSE: { case justification::CLAUSE: {
out << "clause: "; out << "clause: ";
set const& S = j.pos()?m_T[j.clause()]:m_F[j.clause()]; set const& S = j.pos()?(*m_T[j.clause()]):(*m_F[j.clause()]);
for (unsigned i = 0; i < S.size(); ++i) { for (unsigned i = 0; i < S.size(); ++i) {
out << S[i] << " "; out << S[i] << " ";
} }
@ -330,50 +404,38 @@ namespace opt {
} }
} }
struct scoped_select { struct scoped_push {
imp& s; imp& s;
unsigned sz; scoped_push(imp& s):s(s) { s.push(); }
scoped_select(imp& s):s(s), sz(s.m_trail.size()) { ~scoped_push() { s.pop(1); }
}
~scoped_select() {
s.unassign(sz);
}
}; };
struct value_lt { struct value_lt {
vector<rational> const& weights; vector<rational> const& weights;
unsigned_vector const& scores; value_lt(vector<rational> const& weights):
value_lt(vector<rational> const& weights, unsigned_vector const& scores): weights(weights) {}
weights(weights), scores(scores) {}
bool operator()(int v1, int v2) const { bool operator()(int v1, int v2) const {
// - score1 / w1 < - score2 / w2 return weights[v1] > weights[v2];
// <=>
// score1 / w1 > score2 / w2
// <=>
// score1*w2 > score2*w1
unsigned score1 = scores[v1];
unsigned score2 = scores[v2];
rational w1 = weights[v1];
rational w2 = weights[v2];
return rational(score1)*w2 > rational(score2)*w1;
} }
}; };
void inc_score(unsigned clause_id) { void inc_score(unsigned clause_id) {
set const& S = m_T[clause_id]; set const& S = *m_T[clause_id];
if (!has_selected(S)) { if (!has_selected(S)) {
for (unsigned j = 0; j < S.size(); ++j) { for (unsigned j = 0; j < S.size(); ++j) {
++m_scores[S[j]]; ++m_scores[S[j]];
m_score_updated[S[j]] = true;
} }
} }
} }
void dec_score(unsigned clause_id) { void dec_score(unsigned clause_id) {
set const& S = m_T[clause_id]; set const& S = *m_T[clause_id];
if (!has_selected(S)) { if (!has_selected(S)) {
for (unsigned j = 0; j < S.size(); ++j) { for (unsigned j = 0; j < S.size(); ++j) {
SASSERT(m_scores[S[j]] > 0); SASSERT(m_scores[S[j]] > 0);
--m_scores[S[j]]; --m_scores[S[j]];
m_score_updated[S[j]] = true;
} }
} }
} }
@ -390,11 +452,11 @@ namespace opt {
} }
} }
bool L1() { rational L1() {
rational w(0); rational w(m_weight);
scoped_select _sc(*this); scoped_push _sc(*this);
for (unsigned i = 0; !canceled() && i < m_T.size(); ++i) { for (unsigned i = 0; !canceled() && i < m_T.size(); ++i) {
set const& S = m_T[i]; set const& S = *m_T[i];
SASSERT(!S.empty()); SASSERT(!S.empty());
if (!has_selected(S)) { if (!has_selected(S)) {
w += m_weights[select_min(S)]; w += m_weights[select_min(S)];
@ -403,25 +465,42 @@ namespace opt {
} }
} }
} }
if (m_lower < w) { return w;
m_lower = w;
}
return !canceled();
} }
bool L2() { void update_heap() {
rational w(0); for (unsigned i = 0; i < m_scored_weights.size(); ++i) {
scoped_select _sc(*this); if (m_score_updated[i]) {
rational const& old_w = m_scored_weights[i];
rational new_w = rational(m_scores[i])*m_weights_inv[i];
if (new_w > old_w) {
m_scored_weights[i] = new_w;
//m_heap.decreased(i);
}
else if (new_w < old_w) {
m_scored_weights[i] = new_w;
//m_heap.increased(i);
}
m_score_updated[i] = false;
}
}
}
rational L2() {
rational w(m_weight);
scoped_push _sc(*this);
int n = 0; int n = 0;
for (unsigned i = 0; i < m_T.size(); ++i) { for (unsigned i = 0; i < m_T.size(); ++i) {
if (!has_selected(m_T[i])) ++n; if (!has_selected(*m_T[i])) ++n;
} }
value_lt lt(m_weights, m_scores);
update_heap();
value_lt lt(m_scored_weights);
std::sort(m_indices.begin(), m_indices.end(), lt); std::sort(m_indices.begin(), m_indices.end(), lt);
for(unsigned i = 0; i < m_indices.size() && n > 0; ++i) { for(unsigned i = 0; i < m_indices.size() && n > 0; ++i) {
// deg(c) = score(c) // deg(c) = score(c)
// wt(c) = m_weights[c] // wt(c) = m_weights[c]
unsigned idx = m_indices[i]; unsigned idx = m_indices[i];
if (m_scores[idx] == 0) { if (m_scores[idx] == 0) {
break; break;
@ -434,13 +513,10 @@ namespace opt {
} }
n -= m_scores[idx]; n -= m_scores[idx];
} }
if (m_lower < w) { return w;
m_lower = w;
}
return !canceled();
} }
bool L3() { rational L3() {
TRACE("simplex", m_simplex.display(tout);); TRACE("simplex", m_simplex.display(tout););
VERIFY(l_true == m_simplex.make_feasible()); VERIFY(l_true == m_simplex.make_feasible());
TRACE("simplex", m_simplex.display(tout);); TRACE("simplex", m_simplex.display(tout););
@ -450,11 +526,12 @@ namespace opt {
unsynch_mpq_manager& mq = mg.mpq_manager(); unsynch_mpq_manager& mq = mg.mpq_manager();
scoped_mpq c(mq); scoped_mpq c(mq);
mg.ceil(val, c); mg.ceil(val, c);
rational w = rational(c); rational w(c);
if (w > m_lower) { CTRACE("simplex",
m_lower = w; w >= m_weight, tout << w << " " << m_weight << " !!!!\n";
} display(tout););
return true; SASSERT(w >= m_weight);
return w;
} }
void add_simplex_row(bool is_some_true, unsigned sz, unsigned const* S) { void add_simplex_row(bool is_some_true, unsigned sz, unsigned const* S) {
@ -490,9 +567,9 @@ namespace opt {
return result; return result;
} }
bool have_selected(lbool val, vector<set> const& Sets, unsigned& i) { bool have_selected(lbool val, ptr_vector<set> const& Sets, unsigned& i) {
for (i = 0; i < Sets.size(); ++i) { for (i = 0; i < Sets.size(); ++i) {
if (!has_selected(val, Sets[i])) return false; if (!has_selected(val, *Sets[i])) return false;
} }
return true; return true;
} }
@ -508,7 +585,7 @@ namespace opt {
bool values_satisfy_Fs(unsigned& i) { bool values_satisfy_Fs(unsigned& i) {
unsigned j = 0; unsigned j = 0;
for (i = 0; i < m_F.size(); ++i) { for (i = 0; i < m_F.size(); ++i) {
set const& F = m_F[i]; set const& F = *m_F[i];
for (j = 0; j < F.size(); ++j) { for (j = 0; j < F.size(); ++j) {
if (m_model[F[j]] == l_false) { if (m_model[F[j]] == l_false) {
break; break;
@ -575,6 +652,9 @@ namespace opt {
if (val == l_true) { if (val == l_true) {
m_weight += m_weights[idx]; m_weight += m_weights[idx];
update_score(idx, false); update_score(idx, false);
if (m_enable_simplex) {
m_simplex.set_lower(idx, mpq_inf(mpq(1),mpq(0)));
}
} }
SASSERT(val != l_true || m_scores[idx] == 0); SASSERT(val != l_true || m_scores[idx] == 0);
m_value[idx] = val; m_value[idx] = val;
@ -595,6 +675,9 @@ namespace opt {
if (val == l_true) { if (val == l_true) {
m_weight -= m_weights[idx]; m_weight -= m_weights[idx];
update_score(idx, true); update_score(idx, true);
if (m_enable_simplex) {
m_simplex.set_lower(idx, mpq_inf(mpq(0),mpq(0)));
}
} }
if (m_justification[idx].is_axiom()) { if (m_justification[idx].is_axiom()) {
m_replay_idx.push_back(idx); m_replay_idx.push_back(idx);
@ -639,7 +722,7 @@ namespace opt {
bool validate_model() { bool validate_model() {
for (unsigned i = 0; i < m_T.size(); ++i) { for (unsigned i = 0; i < m_T.size(); ++i) {
set const& S = m_T[i]; set const& S = *m_T[i];
bool found = false; bool found = false;
for (unsigned j = 0; !found && j < S.size(); ++j) { for (unsigned j = 0; !found && j < S.size(); ++j) {
found = value(S[j]) == l_true; found = value(S[j]) == l_true;
@ -650,7 +733,7 @@ namespace opt {
SASSERT(found); SASSERT(found);
} }
for (unsigned i = 0; i < m_F.size(); ++i) { for (unsigned i = 0; i < m_F.size(); ++i) {
set const& S = m_F[i]; set const& S = *m_F[i];
bool found = false; bool found = false;
for (unsigned j = 0; !found && j < S.size(); ++j) { for (unsigned j = 0; !found && j < S.size(); ++j) {
found = value(S[j]) != l_true; found = value(S[j]) != l_true;
@ -667,13 +750,13 @@ namespace opt {
bool invariant() { bool invariant() {
for (unsigned i = 0; i < m_fwatch.size(); ++i) { for (unsigned i = 0; i < m_fwatch.size(); ++i) {
for (unsigned j = 0; j < m_fwatch[i].size(); ++j) { for (unsigned j = 0; j < m_fwatch[i].size(); ++j) {
set const& S = m_F[m_fwatch[i][j]]; set const& S = *m_F[m_fwatch[i][j]];
SASSERT(S[0] == i || S[1] == i); SASSERT(S[0] == i || S[1] == i);
} }
} }
for (unsigned i = 0; i < m_twatch.size(); ++i) { for (unsigned i = 0; i < m_twatch.size(); ++i) {
for (unsigned j = 0; j < m_twatch[i].size(); ++j) { for (unsigned j = 0; j < m_twatch[i].size(); ++j) {
set const& S = m_T[m_twatch[i][j]]; set const& S = *m_T[m_twatch[i][j]];
SASSERT(S[0] == i || S[1] == i); SASSERT(S[0] == i || S[1] == i);
} }
} }
@ -692,9 +775,9 @@ namespace opt {
unsigned r = lvl(conflict_l); unsigned r = lvl(conflict_l);
if (conflict_j.is_clause()) { if (conflict_j.is_clause()) {
unsigned clause = conflict_j.clause(); unsigned clause = conflict_j.clause();
vector<unsigned_vector> const& S = conflict_j.pos()?m_T:m_F; ptr_vector<set> const& S = conflict_j.pos()?m_T:m_F;
r = std::max(r, lvl(S[clause][0])); r = std::max(r, lvl((*S[clause])[0]));
r = std::max(r, lvl(S[clause][1])); r = std::max(r, lvl((*S[clause])[1]));
} }
return r; return r;
} }
@ -723,7 +806,7 @@ namespace opt {
unsigned cl = conflict_j.clause(); unsigned cl = conflict_j.clause();
unsigned i = 0; unsigned i = 0;
SASSERT(value(conflict_l) != l_undef); SASSERT(value(conflict_l) != l_undef);
set const& T = conflict_j.pos()?m_T[cl]:m_F[cl]; set const& T = conflict_j.pos()?(*m_T[cl]):(*m_F[cl]);
if (T[0] == conflict_l) { if (T[0] == conflict_l) {
i = 1; i = 1;
} }
@ -823,13 +906,24 @@ namespace opt {
} }
unsigned next_var() { unsigned next_var() {
value_lt lt(m_weights, m_scores); update_heap();
value_lt lt(m_scored_weights);
std::sort(m_indices.begin(), m_indices.end(), lt); std::sort(m_indices.begin(), m_indices.end(), lt);
unsigned idx = m_indices[0]; unsigned idx = m_indices[0];
if (m_scores[idx] == 0) { if (m_scores[idx] == 0) return UINT_MAX;
idx = UINT_MAX;
}
return idx; return idx;
#if 0
int min_val = m_heap.min_value();
if (min_val == -1) {
return UINT_MAX;
}
SASSERT(0 <= min_val && static_cast<unsigned>(min_val) < m_weights.size());
if (m_scores[min_val] == 0) {
return UINT_MAX;
}
return static_cast<unsigned>(min_val);
#endif
} }
bool decide() { bool decide() {
@ -866,7 +960,7 @@ namespace opt {
prune_branch(); prune_branch();
} }
void propagate(unsigned idx, lbool good_val, vector<unsigned_vector>& watch, vector<set>& Fs) void propagate(unsigned idx, lbool good_val, vector<unsigned_vector>& watch, ptr_vector<set>& Fs)
{ {
TRACE("opt", tout << idx << " " << value(idx) << "\n";); TRACE("opt", tout << idx << " " << value(idx) << "\n";);
unsigned_vector& w = watch[idx]; unsigned_vector& w = watch[idx];
@ -876,10 +970,10 @@ namespace opt {
unsigned l = 0; unsigned l = 0;
for (unsigned i = 0; i < sz && !canceled(); ++i, ++l) { for (unsigned i = 0; i < sz && !canceled(); ++i, ++l) {
unsigned clause_id = w[i]; unsigned clause_id = w[i];
set& F = Fs[clause_id]; set& F = *Fs[clause_id];
SASSERT(F.size() >= 2); SASSERT(F.size() >= 2);
unsigned k1 = (F[0] == idx)?0:1; bool k1 = (F[0] != idx);
unsigned k2 = 1 - k1; bool k2 = !k1;
SASSERT(F[k1] == idx); SASSERT(F[k1] == idx);
SASSERT(value(F[k1]) == bad_val); SASSERT(value(F[k1]) == bad_val);
if (value(F[k2]) == good_val) { if (value(F[k2]) == good_val) {
@ -924,27 +1018,35 @@ namespace opt {
} }
bool infeasible_lookahead() { bool infeasible_lookahead() {
// TBD: make this more powerful if (m_enable_simplex && L3() >= m_max_weight) {
// by using L1, L2, L3 pruning criteria. return true;
return (m_weight >= m_max_weight); }
return
(L1() >= m_max_weight) ||
(L2() >= m_max_weight);
} }
void prune_branch() { void prune_branch() {
if (!inconsistent() && infeasible_lookahead()) { if (inconsistent() || !infeasible_lookahead()) {
IF_VERBOSE(4, verbose_stream() << "(hs.prune-branch " << m_weight << ")\n";); return;
m_lemma.reset();
for (unsigned i = m_trail.size(); i > 0; ) {
--i;
unsigned idx = m_trail[i];
if (m_justification[idx].is_decision()) {
SASSERT(value(idx) == l_true);
m_lemma.push_back(idx);
}
}
justification j = add_exists_false(m_lemma.size(), m_lemma.c_ptr());
TRACE("opt", display(tout, j););
set_conflict(m_lemma[0], j);
} }
IF_VERBOSE(4, verbose_stream() << "(hs.prune-branch " << m_weight << ")\n";);
m_lemma.reset();
unsigned i = 0;
rational w(0);
for (; i < m_trail.size() && w < m_max_weight; ++i) {
unsigned idx = m_trail[i];
if (m_justification[idx].is_decision()) {
SASSERT(value(idx) == l_true);
m_lemma.push_back(idx);
w += m_weights[idx];
}
}
// undo the lower bounds.
justification j = add_exists_false(m_lemma.size(), m_lemma.c_ptr());
TRACE("opt", display(tout, j););
set_conflict(m_lemma[0], j);
} }
// TBD: derive strong inequalities and add them to Simplex. // TBD: derive strong inequalities and add them to Simplex.