diff --git a/src/sat/ba_solver.cpp b/src/sat/ba_solver.cpp index eedca9ce9..e77e1172d 100644 --- a/src/sat/ba_solver.cpp +++ b/src/sat/ba_solver.cpp @@ -1739,6 +1739,25 @@ namespace sat { SASSERT(validate_unit_propagation(p, r, l)); } + bool ba_solver::is_extended_binary(ext_justification_idx idx, literal_vector & r) { + constraint const& c = index2constraint(idx); + switch (c.tag()) { + case card_t: { + card const& ca = c.to_card(); + if (ca.size() == ca.k() + 1 && ca.lit() == null_literal) { + r.reset(); + for (literal l : ca) r.push_back(l); + return true; + } + else { + return false; + } + } + default: + return false; + } + } + void ba_solver::simplify(xor& x) { // no-op } @@ -2004,17 +2023,39 @@ namespace sat { /** \brief Lex on (glue, size) */ - struct constraint_glue_lt { + struct constraint_glue_psm_lt { bool operator()(ba_solver::constraint const * c1, ba_solver::constraint const * c2) const { return (c1->glue() < c2->glue()) || - (c1->glue() == c2->glue() && c1->size() < c2->size()); + (c1->glue() == c2->glue() && + (c1->psm() < c2->psm() || + (c1->psm() == c2->psm() && c1->size() < c2->size()))); } }; + void ba_solver::update_psm(constraint& c) const { + unsigned r = 0; + switch (c.tag()) { + case card_t: + for (literal l : c.to_card()) { + if (s().m_phase[l.var()] == (l.sign() ? NEG_PHASE : POS_PHASE)) ++r; + } + break; + case pb_t: + for (wliteral l : c.to_pb()) { + if (s().m_phase[l.second.var()] == (l.second.sign() ? NEG_PHASE : POS_PHASE)) ++r; + } + break; + default: + break; + } + c.set_psm(r); + } + void ba_solver::gc() { - std::stable_sort(m_learned.begin(), m_learned.end(), constraint_glue_lt()); - gc_half("glue"); + for (auto & c : m_learned) update_psm(*c); + std::stable_sort(m_learned.begin(), m_learned.end(), constraint_glue_psm_lt()); + gc_half("glue-psm"); cleanup_constraints(m_learned, true); } diff --git a/src/sat/ba_solver.h b/src/sat/ba_solver.h index 2169f5845..5347cac22 100644 --- a/src/sat/ba_solver.h +++ b/src/sat/ba_solver.h @@ -62,12 +62,13 @@ namespace sat { bool m_removed; literal m_lit; unsigned m_glue; + unsigned m_psm; unsigned m_size; size_t m_obj_size; bool m_learned; unsigned m_id; public: - constraint(tag_t t, unsigned id, literal l, unsigned sz, size_t osz): m_tag(t), m_removed(false), m_lit(l), m_glue(0), m_size(sz), m_obj_size(osz), m_learned(false), m_id(id) {} + constraint(tag_t t, unsigned id, literal l, unsigned sz, size_t osz): m_tag(t), m_removed(false), m_lit(l), m_glue(0), m_psm(0), m_size(sz), m_obj_size(osz), m_learned(false), m_id(id) {} ext_constraint_idx index() const { return reinterpret_cast(this); } unsigned id() const { return m_id; } tag_t tag() const { return m_tag; } @@ -79,7 +80,9 @@ namespace sat { void remove() { m_removed = true; } void nullify_literal() { m_lit = null_literal; } unsigned glue() const { return m_glue; } - void set_glue(unsigned g) { m_glue = g; } + void set_glue(unsigned g) { m_glue = g; } + unsigned psm() const { return m_psm; } + void set_psm(unsigned p) { m_psm = p; } void set_learned(bool f) { m_learned = f; } bool learned() const { return m_learned; } @@ -265,6 +268,7 @@ namespace sat { void subsumption(constraint& c1); void subsumption(card& c1); void gc_half(char const* _method); + void update_psm(constraint& c) const; void mutex_reduction(); typedef vector> lhs_t; @@ -442,6 +446,7 @@ namespace sat { virtual void pop_reinit(); virtual void gc(); virtual double get_reward(literal l, ext_justification_idx idx, literal_occs_fun& occs) const; + virtual bool is_extended_binary(ext_justification_idx idx, literal_vector & r); ptr_vector const & constraints() const { return m_constraints; } diff --git a/src/sat/sat_extension.h b/src/sat/sat_extension.h index 87f1904ed..406cc6421 100644 --- a/src/sat/sat_extension.h +++ b/src/sat/sat_extension.h @@ -43,6 +43,7 @@ namespace sat { virtual bool propagate(literal l, ext_constraint_idx idx) = 0; virtual double get_reward(literal l, ext_constraint_idx idx, literal_occs_fun& occs) const = 0; virtual void get_antecedents(literal l, ext_justification_idx idx, literal_vector & r) = 0; + virtual bool is_extended_binary(ext_justification_idx idx, literal_vector & r) = 0; virtual void asserted(literal l) = 0; virtual check_result check() = 0; virtual lbool resolve_conflict() { return l_undef; } // stores result in sat::solver::m_lemma diff --git a/src/sat/sat_lookahead.cpp b/src/sat/sat_lookahead.cpp index b5229dc54..aaf392ae3 100644 --- a/src/sat/sat_lookahead.cpp +++ b/src/sat/sat_lookahead.cpp @@ -503,6 +503,7 @@ namespace sat { // arcs are added in the opposite direction of implications. // So for implications l => u we add arcs u -> l void lookahead::init_arcs(literal l) { + literal_vector lits; literal_vector const& succ = m_binary[l.index()]; for (unsigned i = 0; i < succ.size(); ++i) { literal u = succ[i]; @@ -512,6 +513,16 @@ namespace sat { add_arc( u, l); } } + for (auto w : m_watches[l.index()]) { + if (w.is_ext_constraint() && m_s.m_ext->is_extended_binary(w.get_ext_constraint_idx(), lits)) { + for (literal u : lits) { + if (u.index() > l.index() && is_stamped(u)) { + add_arc(~l, ~u); + add_arc( u, l); + } + } + } + } } void lookahead::get_scc(literal v) { diff --git a/src/sat/sat_scc.cpp b/src/sat/sat_scc.cpp index ec77ebfbd..15108c7fd 100644 --- a/src/sat/sat_scc.cpp +++ b/src/sat/sat_scc.cpp @@ -33,10 +33,11 @@ namespace sat { struct frame { unsigned m_lidx; + unsigned m_succ_idx; bool m_first; watched * m_it; watched * m_end; - frame(unsigned lidx, watched * it, watched * end):m_lidx(lidx), m_first(true), m_it(it), m_end(end) {} + frame(unsigned lidx, watched * it, watched * end, unsigned sidx = 0):m_lidx(lidx), m_succ_idx(sidx), m_first(true), m_it(it), m_end(end) {} }; typedef svector frames; @@ -75,7 +76,7 @@ namespace sat { index.resize(num_lits, UINT_MAX); lowlink.resize(num_lits, UINT_MAX); in_s.resize(num_lits, false); - literal_vector roots; + literal_vector roots, lits; roots.resize(m_solver.num_vars(), null_literal); unsigned next_index = 0; svector frames; @@ -106,6 +107,7 @@ namespace sat { frame & fr = frames.back(); unsigned l_idx = fr.m_lidx; if (!fr.m_first) { + SASSERT(fr.m_it->is_binary_clause()); // after visiting child literal l2 = fr.m_it->get_literal(); unsigned l2_idx = l2.index();