diff --git a/src/ast/simplifier/poly_simplifier_plugin.h b/src/ast/simplifier/poly_simplifier_plugin.h
index 4e6ae9c15..ed6d506c5 100644
--- a/src/ast/simplifier/poly_simplifier_plugin.h
+++ b/src/ast/simplifier/poly_simplifier_plugin.h
@@ -37,7 +37,7 @@ protected:
     expr * mk_add(expr * arg1, expr * arg2) { expr * args[2] = { arg1, arg2 }; return mk_add(2, args); }
     expr * mk_mul(unsigned num_args, expr * const * args);
     expr * mk_mul(expr * arg1, expr * arg2) { expr * args[2] = { arg1, arg2 }; return mk_mul(2, args); }
-    expr * mk_sub(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_fid, m_SUB, num_args, args); }
+    // expr * mk_sub(unsigned num_args, expr * const * args) { return m_manager.mk_app(m_fid, m_SUB, num_args, args); }
     expr * mk_uminus(expr * arg) { return m_manager.mk_app(m_fid, m_UMINUS, arg); }
 
     void process_monomial(unsigned num_args, expr * const * args, numeral & k, ptr_buffer<expr> & result);
diff --git a/src/cmd_context/check_logic.cpp b/src/cmd_context/check_logic.cpp
index c75c12689..0faddce73 100644
--- a/src/cmd_context/check_logic.cpp
+++ b/src/cmd_context/check_logic.cpp
@@ -187,6 +187,7 @@ struct check_logic::imp {
             m_bvs         = true;
             m_uf          = true;
             m_ints        = true;
+            m_nonlinear   = true; // non-linear 0-1 variables may get eliminated
         }
         else {
             m_unknown_logic = true;
diff --git a/src/sat/sat_solver.cpp b/src/sat/sat_solver.cpp
index d6b39c394..22418ed28 100644
--- a/src/sat/sat_solver.cpp
+++ b/src/sat/sat_solver.cpp
@@ -3180,7 +3180,7 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
     static lbool core_chunking(sat::solver& s, model const& m, sat::bool_var_vector const& vars, sat::literal_vector const& asms, vector<sat::literal_vector>& conseq, unsigned K) {
         sat::literal_vector lambda;
         for (unsigned i = 0; i < vars.size(); i++) {
-            lambda.push_back(sat::literal(i, m[vars[i]] == l_false));
+            lambda.push_back(sat::literal(vars[i], m[vars[i]] == l_false));
         }
         while (!lambda.empty()) {
             IF_VERBOSE(1, verbose_stream() << "(sat-backbone-core " << lambda.size() << " " << conseq.size() << ")\n";);
@@ -3259,9 +3259,9 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
             }
         }
 
-        // is_sat = core_chunking(*this, mdl, vars, asms, conseq, 100);
+        is_sat = core_chunking(*this, mdl, vars, asms, conseq, 100);
 
-        is_sat = get_consequences(asms, lits, conseq);
+        // is_sat = get_consequences(asms, lits, conseq);
         set_model(mdl);
         return is_sat;
     }
@@ -3371,13 +3371,14 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
         propagate(false);
         if (check_inconsistent()) return l_false;
 
-        unsigned num_units = 0, num_iterations = 0;
-        extract_fixed_consequences(num_units, assumptions, unfixed_vars, conseq);
+        unsigned num_iterations = 0;
+        extract_fixed_consequences(unfixed_lits, assumptions, unfixed_vars, conseq); 
         update_unfixed_literals(unfixed_lits, unfixed_vars);
         while (!unfixed_lits.empty()) {
             if (scope_lvl() > 1) {
                 pop(scope_lvl() - 1);
             }
+            propagate(false);
             ++num_iterations;
             checkpoint();
             literal_set::iterator it = unfixed_lits.begin(), end = unfixed_lits.end();
@@ -3389,8 +3390,9 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
                 literal lit = *it;                
                 if (value(lit) != l_undef) {
                     ++num_fixed;
-                    if (value(lit) == l_true && lvl(lit) == 1) {
-                        VERIFY(extract_fixed_consequences(lit, assumptions, unfixed_vars, conseq));
+                    if (lvl(lit) <= 1) {
+                        SASSERT(value(lit) == l_true);
+                        extract_fixed_consequences(lit, assumptions, unfixed_vars, conseq);
                     }
                     continue;
                 }
@@ -3409,18 +3411,13 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
                     ++num_resolves;
                 }
                 if (false && scope_lvl() == 1) {
+                    is_sat = l_undef;
                     break;
                 }
             }
-            if (scope_lvl() == 1) {
-                it = unfixed_lits.begin();
-                for (; it != end; ++it) {
-                    literal lit = *it;
-                    if (value(lit) == l_true) {
-                        VERIFY(extract_fixed_consequences(lit, assumptions, unfixed_vars, conseq));
-                    }
-                }
-            }
+
+            extract_fixed_consequences(unfixed_lits, assumptions, unfixed_vars, conseq);
+
             if (is_sat == l_true) {
                 if (scope_lvl() == 1 && num_resolves > 0) {
                     IF_VERBOSE(1, verbose_stream() << "(sat.get-consequences backjump)\n";);
@@ -3431,6 +3428,7 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
                     if (is_sat == l_undef) {
                         restart();
                     }
+                    extract_fixed_consequences(unfixed_lits, assumptions, unfixed_vars, conseq);
                 }
             }
             if (is_sat == l_false) {
@@ -3440,7 +3438,6 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
             if (is_sat == l_true) {
                 delete_unfixed(unfixed_lits, unfixed_vars);
             }
-            extract_fixed_consequences(num_units, assumptions, unfixed_vars, conseq); 
             update_unfixed_literals(unfixed_lits, unfixed_vars);
             IF_VERBOSE(1, verbose_stream() << "(sat.get-consequences"
                        << " iterations: " << num_iterations
@@ -3492,19 +3489,27 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
         SASSERT(!inconsistent());
         unsigned sz = m_trail.size();
         for (unsigned i = start; i < sz && lvl(m_trail[i]) <= 1; ++i) {
-            if (!extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq)) {
-                for (i = 0; i < sz && lvl(m_trail[i]) <= 1; ++i) {
-                    VERIFY(extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq));
-                }
-                break;
-            }
+            extract_fixed_consequences(m_trail[i], assumptions, unfixed, conseq);
         }
         start = sz;
     }
 
+    void solver::extract_fixed_consequences(literal_set const& unfixed_lits, literal_set const& assumptions, bool_var_set& unfixed_vars, vector<literal_vector>& conseq) {
+        literal_set::iterator it = unfixed_lits.begin(), end = unfixed_lits.end();
+        for (; it != end; ++it) {
+            literal lit = *it;
+            if (lvl(lit) <= 1) {
+                SASSERT(value(lit) == l_true);
+                extract_fixed_consequences(lit, assumptions, unfixed_vars, conseq);
+            }
+        }
+    }
+
     bool solver::check_domain(literal lit, literal lit2) {
         if (!m_antecedents.contains(lit2.var())) {
+            SASSERT(value(lit2) == l_true);
             m_todo_antecedents.push_back(lit2);
+            TRACE("sat", tout << "todo: " << lit2 << " " << value(lit2) << "\n";);
             return false;
         }
         else {
@@ -3514,16 +3519,17 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
 
     bool solver::extract_assumptions(literal lit, index_set& s) {
         justification js = m_justification[lit.var()];
+        TRACE("sat", tout << lit << " " << js << "\n";);
         switch (js.get_kind()) {
         case justification::NONE:
             break;
         case justification::BINARY:
-            if (!check_domain(lit, js.get_literal())) return false;
+            if (!check_domain(lit, ~js.get_literal())) return false;
             s |= m_antecedents.find(js.get_literal().var());
             break;
         case justification::TERNARY:
-            if (!check_domain(lit, js.get_literal1())) return false;
-            if (!check_domain(lit, js.get_literal2())) return false;
+            if (!check_domain(lit, ~js.get_literal1()) ||
+                !check_domain(lit, ~js.get_literal2())) return false;
             s |= m_antecedents.find(js.get_literal1().var());
             s |= m_antecedents.find(js.get_literal2().var());
             break;
@@ -3531,7 +3537,7 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
             clause & c = *(m_cls_allocator.get_clause(js.get_clause_offset()));
             for (unsigned i = 0; i < c.size(); ++i) {
                 if (c[i] != lit) {
-                    if (!check_domain(lit, c[i])) return false;
+                    if (!check_domain(lit, ~c[i])) return false;
                     s |= m_antecedents.find(c[i].var());
                 }
             }
@@ -3565,7 +3571,7 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
     }
 
 
-    bool solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq) {
+    bool solver::extract_fixed_consequences1(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq) {
         index_set s;
         if (m_antecedents.contains(lit.var())) {
             return true;
@@ -3574,16 +3580,9 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
             s.insert(lit.index());
         }
         else {
-            SASSERT(m_todo_antecedents.empty());
             if (!extract_assumptions(lit, s)) {
                 SASSERT(!m_todo_antecedents.empty());
-                while (!m_todo_antecedents.empty()) {
-                    index_set s1;
-                    if (extract_assumptions(m_todo_antecedents.back(), s1)) {
-                        m_todo_antecedents.pop_back();
-                    }
-                }
-                VERIFY (extract_assumptions(lit, s));
+                return false;
             }
             add_assumption(lit);
         }
@@ -3601,6 +3600,16 @@ static void back_remove(sat::literal_vector& lits, sat::literal l) {
         return true;
     }
 
+    void solver::extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq) {
+        SASSERT(m_todo_antecedents.empty());
+        m_todo_antecedents.push_back(lit);
+        while (!m_todo_antecedents.empty()) {
+            if (extract_fixed_consequences1(m_todo_antecedents.back(), assumptions, unfixed, conseq)) {
+                m_todo_antecedents.pop_back();
+            }
+        }
+    }
+
     void solver::asymmetric_branching() {
         if (scope_lvl() > 0 || inconsistent())
             return;
diff --git a/src/sat/sat_solver.h b/src/sat/sat_solver.h
index 091162f23..a26abe1e0 100644
--- a/src/sat/sat_solver.h
+++ b/src/sat/sat_solver.h
@@ -498,7 +498,11 @@ namespace sat {
 
         void extract_fixed_consequences(unsigned& start, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq);
 
-        bool extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq);
+        void extract_fixed_consequences(literal_set const& unfixed_lits, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq);
+
+        void extract_fixed_consequences(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq);
+
+        bool extract_fixed_consequences1(literal lit, literal_set const& assumptions, bool_var_set& unfixed, vector<literal_vector>& conseq);
 
         void update_unfixed_literals(literal_set& unfixed_lits, bool_var_set& unfixed_vars);
 
diff --git a/src/smt/theory_bv.cpp b/src/smt/theory_bv.cpp
index ae2aa95e2..255e2044f 100644
--- a/src/smt/theory_bv.cpp
+++ b/src/smt/theory_bv.cpp
@@ -762,6 +762,21 @@ namespace smt {
         TRACE("bv", tout << mk_pp(cond, get_manager()) << "\n"; tout << l << "\n";); \
     }
 
+    void theory_bv::internalize_sub(app *n) {
+        SASSERT(!get_context().e_internalized(n));                      
+        SASSERT(n->get_num_args() == 2);                                                
+        process_args(n);                                                                
+        ast_manager & m = get_manager();                                                
+        enode * e       = mk_enode(n);                                                  
+        expr_ref_vector arg1_bits(m), arg2_bits(m), bits(m);                            
+        get_arg_bits(e, 0, arg1_bits);                                                  
+        get_arg_bits(e, 1, arg2_bits);                                                  
+        SASSERT(arg1_bits.size() == arg2_bits.size());                                  
+        expr_ref carry(m);
+        m_bb.mk_subtracter(arg1_bits.size(), arg1_bits.c_ptr(), arg2_bits.c_ptr(), bits, carry);    
+        init_bits(e, bits);                                                                
+    }
+
     MK_UNARY(internalize_not,       mk_not);
     MK_UNARY(internalize_redand,    mk_redand);
     MK_UNARY(internalize_redor,     mk_redor);
@@ -848,6 +863,7 @@ namespace smt {
         switch (term->get_decl_kind()) {
         case OP_BV_NUM:         internalize_num(term); return true;
         case OP_BADD:           internalize_add(term); return true;
+        case OP_BSUB:           internalize_sub(term); return true;
         case OP_BMUL:           internalize_mul(term); return true;
         case OP_BSDIV_I:        internalize_sdiv(term); return true;
         case OP_BUDIV_I:        internalize_udiv(term); return true;
diff --git a/src/smt/theory_bv.h b/src/smt/theory_bv.h
index 17d03b412..50e4f9c30 100644
--- a/src/smt/theory_bv.h
+++ b/src/smt/theory_bv.h
@@ -172,6 +172,7 @@ namespace smt {
         bool get_fixed_value(theory_var v, numeral & result) const;
         void internalize_num(app * n);
         void internalize_add(app * n);
+        void internalize_sub(app * n);
         void internalize_mul(app * n);
         void internalize_udiv(app * n);
         void internalize_sdiv(app * n);
diff --git a/src/tactic/portfolio/enum2bv_solver.cpp b/src/tactic/portfolio/enum2bv_solver.cpp
index 9afd97de5..35601f374 100644
--- a/src/tactic/portfolio/enum2bv_solver.cpp
+++ b/src/tactic/portfolio/enum2bv_solver.cpp
@@ -137,8 +137,10 @@ public:
                 SASSERT(num.is_unsigned());
                 expr_ref head(m);
                 ptr_vector<func_decl> const& enums = *dt.get_datatype_constructors(f->get_range());
-                head = m.mk_eq(m.mk_const(f), m.mk_const(enums[num.get_unsigned()]));
-                consequences[i] = m.mk_implies(a, head);
+                if (enums.size() > num.get_unsigned()) {
+                    head = m.mk_eq(m.mk_const(f), m.mk_const(enums[num.get_unsigned()]));
+                    consequences[i] = m.mk_implies(a, head);
+                }
             }
         }
         return r;
diff --git a/src/test/cnf_backbones.cpp b/src/test/cnf_backbones.cpp
index c34e109d3..b95977a46 100644
--- a/src/test/cnf_backbones.cpp
+++ b/src/test/cnf_backbones.cpp
@@ -152,14 +152,13 @@ static void brute_force_consequences(sat::solver& s, sat::literal_vector const&
 
 static lbool core_chunking(sat::solver& s, sat::bool_var_vector& vars, sat::literal_vector const& asms, vector<sat::literal_vector>& conseq, unsigned K) {
     lbool r = s.check(asms.size(), asms.c_ptr());
-    display_status(r);
     if (r != l_true) {
         return r;
     }
     sat::model const & m = s.get_model();
     sat::literal_vector lambda, backbones;
-    for (unsigned i = 1; i < m.size(); i++) {
-        lambda.push_back(sat::literal(i, m[i] == l_false));
+    for (unsigned i = 0; i < vars.size(); i++) {
+        lambda.push_back(sat::literal(vars[i], m[vars[i]] == l_false));
     }
     while (!lambda.empty()) {
         IF_VERBOSE(1, verbose_stream() << "(sat-backbone-core " << lambda.size() << " " << backbones.size() << ")\n";);
@@ -270,10 +269,15 @@ static void cnf_backbones(bool use_chunk, char const* file_name) {
 }
 
 void tst_cnf_backbones(char ** argv, int argc, int& i) {
+    bool use_chunk = i + 1 < argc && argv[i + 1] == std::string("chunk");
+    if (use_chunk) ++i;     
+    char const* file = "";
     if (i + 1 < argc) {
-        bool use_chunk = (i + 2 < argc && argv[i + 1] == std::string("chunk"));
-        if (use_chunk) ++i;        
-        cnf_backbones(use_chunk, argv[i + 1]);
-        ++i;
+        file = argv[i + 1];
     }
+    else {
+        file = argv[1];
+    }
+    cnf_backbones(use_chunk, file);
+    ++i;
 }