From 7c47809973a2da7efed8fa91b40c3f83ceeae130 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Wed, 26 Aug 2015 16:33:53 -0700
Subject: [PATCH] reworking pd-maxres

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/sat/sat_solver.cpp | 90 +++++++++++++++++++++++++++---------------
 src/sat/sat_solver.h   |  3 +-
 src/sat/sat_types.h    |  1 +
 3 files changed, 61 insertions(+), 33 deletions(-)

diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp
index 6755d1778..64eb10148 100644
--- a/src/sat/sat_solver.cpp
+++ b/src/sat/sat_solver.cpp
@@ -926,7 +926,7 @@ namespace sat {
                 svector<literal> blocker;
                 if (!init_weighted_assumptions(num_lits, lits, weights, max_weight, blocker)) {
                     pop_to_base_level();
-                    mk_clause(blocker.size(), blocker.c_ptr());
+                    mk_clause(blocker.size(), blocker.c_ptr());                    
                     goto retry_init_assumptions;
                 }
             }
@@ -948,68 +948,93 @@ namespace sat {
         flet<bool> _min2(m_config.m_minimize_core_partial, false);
         m_conflict_lvl = m_scope_lvl;
         resolve_conflict_for_unsat_core();
-        m_assumptions.pop_back();
     }
 
     bool solver::init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight, 
                                            svector<literal>& blocker) {
         double weight = 0;
         blocker.reset();
+        svector<literal> min_core;
+        bool min_core_valid = false;
         for (unsigned i = 0; !inconsistent() && i < num_lits; ++i) {
             literal lit = lits[i];
             SASSERT(is_external(lit.var()));  
-            m_assumption_set.insert(lit);       
             TRACE("sat", tout << "propagate: " << lit << " " << value(lit) << "\n";);
             SASSERT(m_scope_lvl == 1);
             switch(value(lit)) {
             case l_undef:
+                m_assumption_set.insert(lit);       
                 m_assumptions.push_back(lit);       
                 assign(lit, justification());
                 propagate(false);
                 if (inconsistent()) {
                     resolve_weighted();
-                    pop(1);
-                    push();
-                    for (unsigned j = 0; j < m_assumptions.size(); ++j) {
-                        assign(m_assumptions[j], justification());                        
+                    blocker.reset();
+                    // next time around, the negation of the literal will be implied.
+                    for (unsigned j = 0; j < m_core.size(); ++j) {
+                        blocker.push_back(~m_core[j]);
                     }
-                    propagate(false);
-                    goto post_process_false;
+                    IF_VERBOSE(1, 
+                               verbose_stream() << "undef: " << lit << " : " << blocker << "\n";
+                               verbose_stream() << m_assumptions << "\n";);
+                    // TBD: avoid redoing assignments, bail out for a full assignment.
+                    return false;
                 }
+                blocker.push_back(~lit);
                 break;
                 
-            case l_false: {
+            case l_false: 
+                m_assumption_set.insert(lit);       
                 m_assumptions.push_back(lit);       
                 SASSERT(!inconsistent());
                 set_conflict(justification(), ~lit);
                 resolve_weighted();
-                goto post_process_false;
-            }
+                weight += weights[i];
+                TRACE("sat", tout << "core: " << m_core << "\nassumptions: " << m_assumptions << "\n";);
+                SASSERT(m_core.size() <= m_assumptions.size());
+                SASSERT(m_assumptions.size() <= i+1);
+                if (m_core.size() <= 3) {
+                    m_inconsistent = true;
+                    TRACE("opt", tout << "found small core: " << m_core << "\n";); 
+                    IF_VERBOSE(1, verbose_stream() << "small core: " << m_core << "\n";);
+                    return true;
+                }
+                if (weight >= max_weight) {
+                    ++m_stats.m_blocked_corr_sets;
+                    TRACE("opt", tout << "blocking soft correction set: " << blocker << "\n";); 
+                    // block the current correction set candidate.
+                    IF_VERBOSE(1, verbose_stream() << "blocking " << blocker << "\n";);
+                    return false;
+                }
+                VERIFY(m_assumptions.back() == m_assumption_set.pop());
+                m_assumptions.pop_back();
+                m_inconsistent = false;                
+                if (!min_core_valid || m_core.size() < min_core.size()) {
+                    min_core.reset();
+                    min_core.append(m_core);
+                }
+                blocker.push_back(lit);
+                break;
             case l_true:
                 break;
             }
-            continue;
-
-        post_process_false:
-            weight += weights[i];
-            blocker.push_back(lit);
-            TRACE("sat", tout << "core: " << m_core << "\nassumptions: " << m_assumptions << "\n";);
-            SASSERT(m_core.size() <= m_assumptions.size() + 1);
-            SASSERT(m_assumptions.size() <= i);
-            if (m_core.size() <= 3) {
-                m_inconsistent = true;
-                TRACE("opt", tout << "found small core: " << m_core << "\n";); 
-                return true;
-            }
-            m_inconsistent = false;                
-            if (weight >= max_weight) {
-                ++m_stats.m_blocked_corr_sets;
-                TRACE("opt", tout << "blocking soft correction set: " << blocker.size() << "\n";); 
-                // block the current correction set candidate.
-                return false;
-            }
         }
         TRACE("sat", tout << "initialized\n";);
+        IF_VERBOSE(1, verbose_stream() << blocker << " - " << min_core << "\n";);
+        if (min_core_valid && blocker.size() > min_core.size()) {
+            pop_to_base_level();
+            m_assumption_set.reset();
+            m_assumptions.reset();
+            for (unsigned i = 0; i < min_core.size(); ++i) {
+                literal lit = min_core[i];
+                SASSERT(is_external(lit.var()));  
+                m_assumption_set.insert(lit);       
+                m_assumptions.push_back(lit);       
+                assign(lit, justification());       
+            }
+            propagate(false);
+            SASSERT(inconsistent());
+        }
         return true;
     }
 
@@ -2531,6 +2556,7 @@ namespace sat {
     //
     // -----------------------
     bool solver::check_invariant() const {
+        if (m_cancel) return true;
         integrity_checker checker(*this);
         SASSERT(checker());
         return true;
diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h
index 8c9c613c0..f8f3cd13b 100644
--- a/src/sat/sat_solver.h
+++ b/src/sat/sat_solver.h
@@ -297,7 +297,8 @@ namespace sat {
         lbool bounded_search();
         void init_search();
         void init_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight);
-        bool init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, double max_weight, svector<literal>& blocker);
+        bool init_weighted_assumptions(unsigned num_lits, literal const* lits, double const* weights, 
+                                       double max_weight, svector<literal>& blocker);
         void resolve_weighted();
         void reinit_assumptions();
         bool tracking_assumptions() const;
diff --git a/src/sat/sat_types.h b/src/sat/sat_types.h
index 2def82b80..c0c087e59 100644
--- a/src/sat/sat_types.h
+++ b/src/sat/sat_types.h
@@ -228,6 +228,7 @@ namespace sat {
             return result;
         }
         void insert(literal l) { m_set.insert(l.index()); }
+        literal pop() { return to_literal(m_set.erase()); }
         bool contains(literal l) const { return m_set.contains(l.index()); }
         bool empty() const { return m_set.empty(); }
         unsigned size() const { return m_set.size(); }