From 87c6fc66d60b7d1c0e571a920b7ec9f9a0e8001f Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 11 Feb 2014 17:44:59 +0000
Subject: [PATCH 001/108] sls tactic default

---
 src/tactic/portfolio/smt_strategic_solver.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index ae79446e3..52b0a3c90 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -37,11 +37,13 @@ Notes:
 #include"horn_tactic.h"
 #include"smt_solver.h"
 
+#include"sls_tactic.h"
+
 tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
-        return mk_qfbv_tactic(m, p);
+        return mk_qfbv_sls_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
     else if (logic=="QF_LIA")

From 25378f7989a5d4f38a40e104a3c9727fce3c7b0f Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 18 Feb 2014 14:01:47 +0000
Subject: [PATCH 002/108] some extensions/modifications. versions added.

---
 src/tactic/portfolio/default_tactic.cpp |   3 +-
 src/tactic/sls/sls_evaluator.h          |   4 +-
 src/tactic/sls/sls_tactic.cpp           | 146 ++++++++++++--
 src/tactic/sls/sls_tracker.h            | 249 +++++++++++++++++++++---
 versions/z3-crsat-0.01.txt              |  12 ++
 versions/z3-gsat-0.01.txt               |  10 +
 versions/z3-gsat-res-0.01.txt           |  10 +
 versions/z3-wsat-0.01.txt               |  12 ++
 versions/z3-wsat-0.01b.txt              |  12 ++
 versions/z3-wsat-0.01c.txt              |  12 ++
 versions/z3-wsat-0.01d.txt              |  11 ++
 versions/z3-wsat-0.01e.txt              |  11 ++
 versions/z3-wsat-0.02.txt               |  13 ++
 versions/z3-wsat-res-0.01.txt           |  13 ++
 14 files changed, 470 insertions(+), 48 deletions(-)
 create mode 100644 versions/z3-crsat-0.01.txt
 create mode 100644 versions/z3-gsat-0.01.txt
 create mode 100644 versions/z3-gsat-res-0.01.txt
 create mode 100644 versions/z3-wsat-0.01.txt
 create mode 100644 versions/z3-wsat-0.01b.txt
 create mode 100644 versions/z3-wsat-0.01c.txt
 create mode 100644 versions/z3-wsat-0.01d.txt
 create mode 100644 versions/z3-wsat-0.01e.txt
 create mode 100644 versions/z3-wsat-0.02.txt
 create mode 100644 versions/z3-wsat-res-0.01.txt

diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 9ecc16ecf..b28b7bec0 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -28,10 +28,11 @@ Notes:
 #include"probe_arith.h"
 #include"quant_tactics.h"
 #include"qffpa_tactic.h"
+#include"sls_tactic.h"
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
+                                        cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 77ff50454..61305386e 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -584,8 +584,8 @@ public:
         run_update(cur_depth);
     }
 
-     void randomize_local(goal_ref const & g) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g);
+     void randomize_local(goal_ref const & g, unsigned int flip) {
+        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
 
         // Randomize _all_ candidates:
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index ea5d60668..c84e68730 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -35,6 +35,17 @@ Notes:
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
 
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 30
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
+#define _VNS_ 0
+#define _WEIGHT_DIST_ 3
+#define _WEIGHT_DIST_FACTOR_ 0.1
+
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
 #include"sls_tracker.h"
@@ -257,7 +268,7 @@ class sls_tactic : public tactic {
             // inversion doesn't make sense, let's do a flip instead.
             if (mt == MV_INV) mt = MV_FLIP;
 
-            ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g);                
+			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
@@ -303,6 +314,82 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(new_value);
         }
 
+        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz, max_bv_sz = 0;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+				if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+
+					// try to flip lsb
+					mk_flip(srt, old_value, 0, temp);                
+	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+	                    new_bit = 0;
+	                    move = MV_FLIP;
+					}
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+
+#if _VNS_ == 1
+			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+			if (new_score <= score)
+			for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+				if (j < bv_sz)
+				{
+					mk_flip(srt, old_value, j, temp);                
+
+	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+	                    new_bit = j;
+	                    move = MV_FLIP;
+	                }
+				}
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+			m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -372,22 +459,29 @@ class sls_tactic : public tactic {
         
             unsigned plateau_cnt = 0;
 
-            while (plateau_cnt < m_plateau_limit) {                
-
+			// Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
                 do {
                     checkpoint();
             
                     old_score = score;
                     new_const = (unsigned)-1;
                         
-                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g);
+					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
 
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
 
+#if _VNS_
+                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
                     score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-
+#endif
                     if (new_const == static_cast<unsigned>(-1)) {
                         TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
                                         for (unsigned i = 0; i < g->size(); i++) {
@@ -400,9 +494,11 @@ class sls_tactic : public tactic {
                                         for (unsigned i = 0; i < g->size(); i++)
                                             tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
                                             m_tracker.get_score(g->form(i)) << std::endl; );
+						// Andreas: If new_const == -1, shouldn't score = old_score anyway?
                         score = old_score;
                     }
                     else {
+						// Andreas: Why does randomizing not count as a move? (Now it does.)
                         m_stats.m_moves++;
                         func_decl * fd = to_evaluate[new_const];
 
@@ -441,6 +537,7 @@ class sls_tactic : public tactic {
 
                     if (score >= 1.0) {
                         // score could theoretically be imprecise.
+						// Andreas: Can it only be imprecise in one direction?
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -451,19 +548,30 @@ class sls_tactic : public tactic {
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
+					/*
+					if (m_stats.m_moves % 100 == 0)
+					{
+						verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+						verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+					}*/
                 }
                 while (score > old_score && res == l_undef);                
-
-                if (score != old_score)
+				
+				// Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                if (score != old_score) {
+					report_tactic_progress("This should not happen I guess.", plateau_cnt);
                     plateau_cnt = 0;
-                else {
+				} else {
+					m_stats.m_moves++;
                     plateau_cnt++;
-                    if (plateau_cnt < m_plateau_limit) {
+					//report_tactic_progress("Plateau.", plateau_cnt);
+					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
-                        m_evaluator.randomize_local(g);
+						m_evaluator.randomize_local(g, m_stats.m_moves);
                         //mk_random_move(g);
                         score = top_score(g);
-                    }
+                    //}
                 }
             }
 
@@ -484,7 +592,8 @@ class sls_tactic : public tactic {
         
             do {
                 checkpoint();
-                if ((m_stats.m_restarts % 100) == 0)                        
+				// Andreas: I think restarts are too impotant to ignore 99% of them are happening...
+                //if ((m_stats.m_restarts % 100) == 0)                        
                     report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 
                 res = search(g);
@@ -492,9 +601,12 @@ class sls_tactic : public tactic {
                 if (res == l_undef)
                     m_tracker.randomize();
             }
-            while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
-            if (res == l_true) {                
+			verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+
+            if (res == l_true) {    
+				report_tactic_progress("Number of flips:", m_stats.m_moves);
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -633,7 +745,13 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
+#if _CNF_
+						// Andreas: We will probably never use this. CNF sucks.
+                        mk_cnf_tactic(m, p));
+#else
+						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
+#endif
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 7fbafec60..1061bd90e 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -28,8 +28,8 @@ class sls_tracker {
     random_gen            m_rng;
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
-    mpz                   m_zero, m_one, m_two;    
-    
+    mpz                   m_zero, m_one, m_two;   
+	    
     struct value_score { 
         value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { };
         ~value_score() { if (m) m->del(value); }
@@ -249,12 +249,46 @@ public:
         }
     }
 
-    void initialize(goal_ref const & g) {
+	void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
+		if (m_manager.is_and(e) || m_manager.is_or(e)) {
+			app * a = to_app(e);
+			expr * const * args = a->get_args();
+			unsigned int sz = a->get_num_args();
+			for (unsigned int i = 0; i < sz; i++) {
+		        expr * q = args[i];
+				initialize_recursive(proc, visited, q);
+			}
+		}
+		for_each_expr(proc, visited, e);
+ 	}
+
+	void initialize_recursive(expr * e) {
+		if (m_manager.is_and(e) || m_manager.is_or(e)) {
+			app * a = to_app(e);
+			expr * const * args = a->get_args();
+			unsigned int sz = a->get_num_args();
+			for (unsigned int i = 0; i < sz; i++) {
+		        expr * q = args[i];
+				initialize_recursive(q);
+			}
+		}
+		ptr_vector<func_decl> t;
+        m_constants_occ.insert_if_not_there(e, t);
+        find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
+        expr_fast_mark1 visited;
+        quick_for_each_expr(ffd_proc, visited, e);
+ 	}
+
+	void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);                
+            expr * e = g->form(i);
+			// Andreas: Maybe not fully correct.
+#if _FOCUS_ == 2
+			initialize_recursive(proc, visited, e);
+#endif
             for_each_expr(proc, visited, e);
         }
 
@@ -262,6 +296,10 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
+			// Andreas: Maybe not fully correct.
+#if _FOCUS_ == 2
+			initialize_recursive(e);
+#endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -382,8 +420,6 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
     }              
 
-#define _SCORE_AND_MIN
-
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
@@ -400,30 +436,41 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            #ifdef _SCORE_AND_MIN
-            double min = 1.0;
+			// Andreas: Seems to have no effect. Probably it does not even occur.
+#if _SCORE_AND_AVG_
+            double sum = 0.0;
+            for (unsigned i = 0; i < a->get_num_args(); i++)
+                sum += get_score(args[i]);
+            res = sum / (double) a->get_num_args();
+#else
+			double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur < min) min = cur;
             }
             res = min;
-            #else 
-            double sum = 0.0;
-            for (unsigned i = 0; i < a->get_num_args(); i++)
-                sum += get_score(args[i]);
-            res = sum / (double) a->get_num_args();
-            #endif
+#endif
         }
         else if (m_manager.is_or(n)) {
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            double max = 0.0;
+			// Andreas: Seems to have no effect. Probably it is still too similar to the original version.
+#if _SCORE_OR_MUL_
+			double inv = 1.0;
+            for (unsigned i = 0; i < a->get_num_args(); i++) {
+                double cur = get_score(args[i]);
+                inv *= (1.0 - get_score(args[i]));
+            }
+            res = 1.0 - inv;
+#else
+			double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur > max) max = cur;
             }
             res = max;
+#endif
         }
         else if (m_manager.is_ite(n)) {
             SASSERT(!negated);
@@ -468,7 +515,7 @@ public:
                     }
                     m_mpz_manager.machine_div(diff, m_two, diff);
                 }
-                res = 1.0 - (hamming_distance / (double) bv_sz);                    
+                res = 1.0 - (hamming_distance / (double) bv_sz);
                 #else                    
                 rational r(diff);
                 r /= m_powers(bv_sz);
@@ -503,7 +550,7 @@ public:
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
                     res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-                    m_mpz_manager.del(diff);
+					m_mpz_manager.del(diff);
                 }
             }
             else {
@@ -564,7 +611,7 @@ public:
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
-            m_mpz_manager.del(x);
+			m_mpz_manager.del(x);
             m_mpz_manager.del(y);                
         }
         else if (m_manager.is_not(n)) {                
@@ -598,6 +645,20 @@ public:
 
         SASSERT(res >= 0.0 && res <= 1.0);
 
+#if _WEIGHT_DIST_
+		app * a = to_app(n);
+		family_id afid = a->get_family_id();
+		if (afid == m_bv_util.get_family_id())
+#endif
+#if _WEIGHT_DIST_ == 1
+		if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+#elif _WEIGHT_DIST_ == 2
+		res *= res;
+#elif _WEIGHT_DIST_ == 3
+		if (res < 1.0) res = 0.0;
+#endif
+
+
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
@@ -647,7 +708,111 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g) {
+	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+        for (unsigned i = 0; i < sz; i++) {
+            expr * q = g->form(i);
+            if (m_mpz_manager.eq(get_value(q), m_one))
+                continue;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+        }
+        return m_temp_constants;
+	}
+
+	expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+			for (unsigned i = pos; i < sz; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+		            return q;
+			}
+			for (unsigned i = 0; i < pos; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+		            return q;
+            }
+			return 0;
+	}
+
+	ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+			expr * q = get_unsat_assertion(g, sz, pos);
+            // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
+			if (!q)
+				return m_temp_constants;
+
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+	        return m_temp_constants;
+	}
+
+	ptr_vector<func_decl> & go_deeper(expr * e) {
+			if (m_manager.is_bool(e)) {
+				if (m_manager.is_and(e)) {
+					app * a = to_app(e);
+					expr * const * args = a->get_args();
+				    // Andreas: might be used for guided branching
+					//for (unsigned i = 0; i < a->get_num_args(); i++) {
+						//double cur = get_score(args[i]);
+					//}
+					// Andreas: A random number is better here since reusing flip will cause patterns.
+					unsigned int sz = a->get_num_args();
+					unsigned int pos = get_random_uint(16) % sz;
+					for (unsigned int i = pos; i < sz; i++) {
+		                expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+					}
+					for (unsigned int i = 0; i < pos; i++) {
+						expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+		            }
+		        }
+				else if (m_manager.is_or(e)) {
+					app * a = to_app(e);
+					expr * const * args = a->get_args();
+					unsigned int sz = a->get_num_args();
+					unsigned int pos = get_random_uint(16) % sz;
+					for (unsigned int i = pos; i < sz; i++) {
+		                expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+					}
+					for (unsigned int i = 0; i < pos; i++) {
+						expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+		            }
+		        }
+			}
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+	        return m_temp_constants;
+	}
+
+	ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+		expr * q = get_unsat_assertion(g, sz, pos);
+        if (!q)
+			return m_temp_constants;
+
+		return go_deeper(q);
+	}
+
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
@@ -655,19 +820,41 @@ public:
         }
         else {
             m_temp_constants.reset();
-            for (unsigned i = 0; i < sz; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.eq(get_value(q), m_one))
-                    continue;
-                ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
-                unsigned sz2 = this_decls.size();
-                for (unsigned j = 0; j < sz2; j++) {
-                    func_decl * fd = this_decls[j];
-                    if (!m_temp_constants.contains(fd))
-                        m_temp_constants.push_back(fd);
-                }
+#if _FOCUS_ == 1
+#if _BFS_ == 3
+			unsigned int pos = 0;
+			double max = get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+				expr * e = g->form(i);
+                double q = get_score(e);
+				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-            return m_temp_constants;
+#elif _BFS_ == 2
+			unsigned int pos = 0;
+			double min = get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+				expr * e = g->form(i);
+                double q = get_score(e);
+				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+            }
+#elif _BFS_ == 1
+			unsigned int pos = flip % m_constants.size();
+#else
+			unsigned int pos = get_random_uint(16) % m_constants.size();
+#endif
+			return get_unsat_constants_walksat(g, sz, pos);
+#elif _FOCUS_ == 2
+#if _BFS_
+			unsigned int pos = flip % m_constants.size();
+#else
+			unsigned int pos = get_random_uint(16) % m_constants.size();
+#endif
+			return get_unsat_constants_crsat(g, sz, pos);
+#else
+			return get_unsat_constants_gsat(g, sz);
+#endif
         }
     }
 };
diff --git a/versions/z3-crsat-0.01.txt b/versions/z3-crsat-0.01.txt
new file mode 100644
index 000000000..49e1a1525
--- /dev/null
+++ b/versions/z3-crsat-0.01.txt
@@ -0,0 +1,12 @@
+More focused (_FOCUS_ == 2) WalkSAT version.
+Variables are chosen among candidates in only one unsatisfied bit-vector term.
+Flip rate slightly slower; probably due to larger hash-table and recursive formula structure.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 3
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-gsat-0.01.txt b/versions/z3-gsat-0.01.txt
new file mode 100644
index 000000000..eb806a67f
--- /dev/null
+++ b/versions/z3-gsat-0.01.txt
@@ -0,0 +1,10 @@
+Basic GSAT version.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 0
+#define _FOCUS_ 0
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-gsat-res-0.01.txt b/versions/z3-gsat-res-0.01.txt
new file mode 100644
index 000000000..6a211f2bc
--- /dev/null
+++ b/versions/z3-gsat-res-0.01.txt
@@ -0,0 +1,10 @@
+Basic GSAT version corresponding to Christoph's original code.
+Restarts after 100 plateaus.
+
+#define _CNF_ 0
+#define _BFS_ 0
+#define _FOCUS_ 0
+#define _RESTARTS_ 1
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt
new file mode 100644
index 000000000..141193f76
--- /dev/null
+++ b/versions/z3-wsat-0.01.txt
@@ -0,0 +1,12 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Flip rate increased by roughly 10%-300%.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt
new file mode 100644
index 000000000..2c0c0e7ad
--- /dev/null
+++ b/versions/z3-wsat-0.01b.txt
@@ -0,0 +1,12 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Chooses a random top level assertion instead of using a BFS approach (_BFS_ == 0).
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 0
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01c.txt b/versions/z3-wsat-0.01c.txt
new file mode 100644
index 000000000..223560e08
--- /dev/null
+++ b/versions/z3-wsat-0.01c.txt
@@ -0,0 +1,12 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+AND is scored by average; OR is scored by inverse multiplication.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 1
+#define _SCORE_OR_MUL_ 1
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01d.txt b/versions/z3-wsat-0.01d.txt
new file mode 100644
index 000000000..072191370
--- /dev/null
+++ b/versions/z3-wsat-0.01d.txt
@@ -0,0 +1,11 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion with MINIMAL top_score.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 2
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01e.txt b/versions/z3-wsat-0.01e.txt
new file mode 100644
index 000000000..b018c5e0d
--- /dev/null
+++ b/versions/z3-wsat-0.01e.txt
@@ -0,0 +1,11 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion with MAXIMAL top_score.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 3
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.02.txt b/versions/z3-wsat-0.02.txt
new file mode 100644
index 000000000..34dcb157c
--- /dev/null
+++ b/versions/z3-wsat-0.02.txt
@@ -0,0 +1,13 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Score function reduced to 0/1.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
+#define _WEIGHTED_DIST_ 1
\ No newline at end of file
diff --git a/versions/z3-wsat-res-0.01.txt b/versions/z3-wsat-res-0.01.txt
new file mode 100644
index 000000000..575180a59
--- /dev/null
+++ b/versions/z3-wsat-res-0.01.txt
@@ -0,0 +1,13 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Flip rate increased by roughly 10%-300% compared to GSAT.
+Restarts after 100 plateaus.
+Fps slightly decreased due to restarts. 
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 1
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file

From 853ce522ccda06788da56198d9c3808df4a6cd73 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Sun, 9 Mar 2014 15:42:51 +0000
Subject: [PATCH 003/108] plenty of new stuff

---
 src/sat/tactic/sat_tactic.cpp                 |   4 +-
 src/tactic/portfolio/default_tactic.cpp       |   1 +
 src/tactic/portfolio/smt_strategic_solver.cpp |   1 +
 src/tactic/sls/sls_evaluator.h                | 323 ++++++++-
 src/tactic/sls/sls_tactic.cpp                 | 661 ++++++++++++++++--
 src/tactic/sls/sls_tracker.h                  | 345 ++++++++-
 versions/z3-wsat-0.01.txt                     |   4 +-
 versions/z3-wsat-0.01b.txt                    |   4 +-
 8 files changed, 1235 insertions(+), 108 deletions(-)

diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp
index d48994861..717bf7007 100644
--- a/src/sat/tactic/sat_tactic.cpp
+++ b/src/sat/tactic/sat_tactic.cpp
@@ -66,7 +66,9 @@ class sat_tactic : public tactic {
             CASSERT("sat_solver", m_solver.check_invariant());
             IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver.display_status(verbose_stream()););
             TRACE("sat_dimacs", m_solver.display_dimacs(tout););
-            
+			//m_solver.display_dimacs(std::cerr);
+            //exit(0);
+
             lbool r = m_solver.check();
             if (r == l_false) {
                 g->assert_expr(m.mk_false(), 0, 0);
diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index b28b7bec0..53da9a159 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -33,6 +33,7 @@ Notes:
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
                                         cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
+  //                                      cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),
diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index 52b0a3c90..f63b4fd8c 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -43,6 +43,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
+   //     return mk_qfbv_tactic(m, p);
         return mk_qfbv_sls_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 61305386e..eec9524a9 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -34,6 +34,9 @@ class sls_evaluator {
     powers              & m_powers;
     expr_ref_buffer       m_temp_exprs;
     vector<ptr_vector<expr> > m_traversal_stack;
+#if _EARLY_PRUNE_
+    vector<ptr_vector<expr> > m_traversal_stack_bool;
+#endif
 
 public:
     sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : 
@@ -519,11 +522,15 @@ public:
         }    
     }
 
-    void run_update(unsigned cur_depth) {
+    void run_serious_update(unsigned cur_depth) {
         // precondition: m_traversal_stack contains the entry point(s)
         expr_fast_mark1 visited;
         mpz new_value;
 
+#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
+		double new_score;
+#endif
+
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -533,8 +540,92 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-                m_tracker.set_score(cur, m_tracker.score(cur));
 
+#if _REAL_RS_ || _REAL_PBFS_
+				if (!m_tracker.has_uplinks(cur))
+				{
+					if (m_mpz_manager.eq(new_value,m_one))
+						m_tracker.make_assertion(cur);
+					else
+						m_tracker.break_assertion(cur);
+				}
+#endif
+
+#if _EARLY_PRUNE_
+				new_score = m_tracker.score(cur);
+#if _CACHE_TOP_SCORE_
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+				m_tracker.set_score(cur, new_score);
+				m_tracker.set_score_prune(cur, new_score);
+#else
+#if _CACHE_TOP_SCORE_
+				new_score = m_tracker.score(cur);
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+				m_tracker.set_score(cur, new_score);
+#else
+				m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+#endif			
+                if (m_tracker.has_uplinks(cur)) {
+                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                    for (unsigned j = 0; j < ups.size(); j++) {
+                        expr * next = ups[j];
+                        unsigned next_d = m_tracker.get_distance(next);
+                        SASSERT(next_d < cur_depth);
+                        if (!visited.is_marked(next)) {
+                            m_traversal_stack[next_d].push_back(next);
+                            visited.mark(next);
+                        }
+                    }
+                }
+            }
+
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        m_mpz_manager.del(new_value);
+    }
+
+    void run_update(unsigned cur_depth) {
+        // precondition: m_traversal_stack contains the entry point(s)
+        expr_fast_mark1 visited;
+        mpz new_value;
+
+#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
+		double new_score;
+#endif
+
+        SASSERT(cur_depth < m_traversal_stack.size());
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
+
+            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+                expr * cur = cur_depth_exprs[i];
+
+                (*this)(to_app(cur), new_value);
+                m_tracker.set_value(cur, new_value);
+#if _EARLY_PRUNE_
+				new_score = m_tracker.score(cur);
+#if _CACHE_TOP_SCORE_
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+				m_tracker.set_score(cur, new_score);
+				m_tracker.set_score_prune(cur, new_score);
+#else
+#if _CACHE_TOP_SCORE_
+				new_score = m_tracker.score(cur);
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+				m_tracker.set_score(cur, new_score);
+#else
+				m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+#endif			
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -569,8 +660,11 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-
+#if _REAL_RS_ || _REAL_PBFS_
+		run_serious_update(max_depth);
+#else
         run_update(max_depth);
+#endif
     }
 
     void update(func_decl * fd, const mpz & new_value) {
@@ -584,6 +678,196 @@ public:
         run_update(cur_depth);
     }
 
+    void serious_update(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+        if (m_traversal_stack.size() <= cur_depth) 
+            m_traversal_stack.resize(cur_depth+1);
+        m_traversal_stack[cur_depth].push_back(ep);
+
+        run_serious_update(cur_depth);
+    }
+
+#if _EARLY_PRUNE_
+    unsigned run_update_bool_prune(unsigned cur_depth) {
+        expr_fast_mark1 visited;
+
+		double prune_score, new_score;
+		unsigned pot_benefits = 0;
+ 		SASSERT(cur_depth < m_traversal_stack_bool.size());
+ 
+        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+
+        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+            expr * cur = cur_depth_exprs[i];
+
+			new_score = m_tracker.score(cur); 
+#if _CACHE_TOP_SCORE_
+			if (!m_tracker.has_uplinks(cur))
+				m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+			prune_score = m_tracker.get_score_prune(cur);
+            m_tracker.set_score(cur, new_score);
+
+			if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+				pot_benefits = 1;
+			if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+				pot_benefits = 1;
+
+            if (m_tracker.has_uplinks(cur)) {
+                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                for (unsigned j = 0; j < ups.size(); j++) {
+                    expr * next = ups[j];
+                    unsigned next_d = m_tracker.get_distance(next);
+                    SASSERT(next_d < cur_depth);
+                    if (!visited.is_marked(next)) {
+						m_traversal_stack_bool[next_d].push_back(next);
+                        visited.mark(next);
+                    }
+                }
+            }
+			else
+			{
+			}
+		}
+
+		cur_depth_exprs.reset();
+        cur_depth--;
+ 
+		while (cur_depth != static_cast<unsigned>(-1)) {
+			ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+			if (pot_benefits)
+			{
+				unsigned cur_size = cur_depth_exprs.size();
+				for (unsigned i = 0; i < cur_size; i++) {
+					expr * cur = cur_depth_exprs[i];
+
+#if _CACHE_TOP_SCORE_
+					new_score = m_tracker.score(cur); 
+					if (!m_tracker.has_uplinks(cur))
+						m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+					m_tracker.set_score(cur, new_score);
+#else
+					m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+					if (m_tracker.has_uplinks(cur)) {
+						ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+						for (unsigned j = 0; j < ups.size(); j++) {
+							expr * next = ups[j];
+							unsigned next_d = m_tracker.get_distance(next);
+							SASSERT(next_d < cur_depth);
+							if (!visited.is_marked(next)) {
+								m_traversal_stack_bool[next_d].push_back(next);
+								visited.mark(next);
+							}
+						}
+					}
+				}
+			}
+			cur_depth_exprs.reset();
+			cur_depth--;
+		}
+
+		return pot_benefits;
+    }
+
+    void run_update_prune(unsigned max_depth) {
+        // precondition: m_traversal_stack contains the entry point(s)
+        expr_fast_mark1 visited;
+        mpz new_value;
+
+		unsigned cur_depth = max_depth;
+        SASSERT(cur_depth < m_traversal_stack.size());
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
+
+            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+                expr * cur = cur_depth_exprs[i];
+
+                (*this)(to_app(cur), new_value);
+                m_tracker.set_value(cur, new_value);
+				// should always have uplinks ...
+                if (m_tracker.has_uplinks(cur)) {
+                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                    for (unsigned j = 0; j < ups.size(); j++) {
+                        expr * next = ups[j];
+                        unsigned next_d = m_tracker.get_distance(next);
+                        SASSERT(next_d < cur_depth);
+                        if (!visited.is_marked(next)) {
+							if (m_manager.is_bool(next))
+								m_traversal_stack_bool[max_depth].push_back(next);
+							else
+								m_traversal_stack[next_d].push_back(next);
+                            visited.mark(next);
+                        }
+                    }
+                }
+            }
+
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        m_mpz_manager.del(new_value);
+    }
+
+    unsigned update_prune(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+
+		if (m_traversal_stack_bool.size() <= cur_depth)
+            m_traversal_stack_bool.resize(cur_depth+1);
+		if (m_traversal_stack.size() <= cur_depth) 
+				m_traversal_stack.resize(cur_depth+1);
+
+		if (m_manager.is_bool(ep))
+	        m_traversal_stack_bool[cur_depth].push_back(ep);
+		else
+		{
+	        m_traversal_stack[cur_depth].push_back(ep);
+			run_update_prune(cur_depth);
+		}
+		return run_update_bool_prune(cur_depth);
+    }
+#endif
+
+	void randomize_local(expr * e, unsigned int flip) {
+        ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
+
+        // Randomize _one_ candidate:
+        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
+        func_decl * fd = unsat_constants[r];
+#if _PERC_CHANGE_
+        sort * srt = fd->get_range();
+		mpz temp;
+
+		if (m_manager.is_bool(srt))
+            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+		else
+        {
+			mpz temp2, mask;
+			unsigned bv_sz = m_bv_util.get_bv_size(srt);
+			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+
+			for (unsigned bit = 0; bit < bv_sz; bit++)
+				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+	            {
+	                m_mpz_manager.set(mask, m_powers(bit));
+					m_mpz_manager.bitwise_xor(temp, mask, temp2);
+	                m_mpz_manager.set(temp, temp2);
+		        }
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(temp2);
+		}
+#else
+		mpz temp = m_tracker.get_random(fd->get_range());
+#endif
+		update(fd, temp);
+        m_mpz_manager.del(temp);
+    } 
+
      void randomize_local(goal_ref const & g, unsigned int flip) {
         ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
 
@@ -603,8 +887,37 @@ public:
         // Randomize _one_ candidate:
         unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
         func_decl * fd = unsat_constants[r];
-        mpz temp = m_tracker.get_random(fd->get_range());
-        update(fd, temp);
+#if _PERC_CHANGE_
+        sort * srt = fd->get_range();
+		mpz temp;
+
+		if (m_manager.is_bool(srt))
+            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+		else
+        {
+			mpz temp2, mask;
+			unsigned bv_sz = m_bv_util.get_bv_size(srt);
+			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+
+			for (unsigned bit = 0; bit < bv_sz; bit++)
+				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+	            {
+	                m_mpz_manager.set(mask, m_powers(bit));
+					m_mpz_manager.bitwise_xor(temp, mask, temp2);
+	                m_mpz_manager.set(temp, temp2);
+		        }
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(temp2);
+		}
+#else
+		mpz temp = m_tracker.get_random(fd->get_range());
+#endif
+
+#if _REAL_RS_ || _REAL_PBFS_
+		serious_update(fd, temp);
+#else
+		update(fd, temp);
+#endif
         m_mpz_manager.del(temp);
 
         TRACE("sls", /*tout << "Randomization candidates: ";
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index c84e68730..3d5e3e438 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -35,16 +35,102 @@ Notes:
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
 
-#define _CNF_ 0
-#define _BFS_ 1
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
 #define _FOCUS_ 1
+
+// do we use restarts?
+// 0 = no, otherwise the value defines the maximum number of moves
 #define _RESTARTS_ 0
-#define _TIMELIMIT_ 30
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
 #define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
 #define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
 #define _VNS_ 0
-#define _WEIGHT_DIST_ 3
-#define _WEIGHT_DIST_FACTOR_ 0.1
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 0
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.25
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 0
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 0.01
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+#define _PROBABILISTIC_UCT_ 0
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 1
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 1
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 1
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 1
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
+	InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+	InvalidConfiguration;
+#endif
+
 
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
@@ -57,12 +143,17 @@ class sls_tactic : public tactic {
         stopwatch       m_stopwatch;    
         unsigned        m_full_evals;
         unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+
         stats() :
             m_restarts(0),
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
+			m_umins(0),
+			m_mul2s(0),
+			m_mul3s(0),
+			m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -92,7 +183,9 @@ class sls_tactic : public tactic {
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;        
+		ptr_vector<mpz> m_old_values;
+		
+        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
 
         imp(ast_manager & m, params_ref const & p, stats & s) : 
             m_manager(m),
@@ -174,13 +267,20 @@ class sls_tactic : public tactic {
             #else
             double top_sum = 0.0;
             unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                top_sum += m_tracker.get_score(g->form(i));
+			for (unsigned i = 0; i < sz; i++) {
+				expr * e = g->form(i);
+                top_sum += m_tracker.get_score(e);
             }
-            TRACE("sls_top", tout << "Score distribution:"; 
+
+			TRACE("sls_top", tout << "Score distribution:"; 
                                     for (unsigned i = 0; i < sz; i++)
                                         tout << " " << m_tracker.get_score(g->form(i));
                                     tout << " AVG: " << top_sum / (double) sz << std::endl; );
+
+#if _CACHE_TOP_SCORE_
+			m_tracker.set_top_sum(top_sum);
+#endif
+
             return top_sum / (double) sz;
             #endif
         }
@@ -191,22 +291,54 @@ class sls_tactic : public tactic {
             return top_score(g);
         }
 
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
+        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+			m_evaluator.serious_update(fd, new_value);
             m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+			return (m_tracker.get_top_sum() / g->size());
+#else
             return top_score(g);
+#endif
         }
 
+        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+			m_evaluator.update(fd, new_value);
+            m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+			return (m_tracker.get_top_sum() / g->size());
+#else
+            return top_score(g);
+#endif
+        }
+
+#if _EARLY_PRUNE_
+        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_stats.m_incr_evals++;
+			if (m_evaluator.update_prune(fd, new_value))
+#if _CACHE_TOP_SCORE_
+				return (m_tracker.get_top_sum() / g->size());
+#else
+	            return top_score(g);
+#endif
+			else
+				return 0.0;
+        }
+#endif
+
+		// checks whether the score outcome of a given move is better than the previous score
         bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
-        
+
             #ifdef Z3DEBUG
             mpz old_value;
             m_mpz_manager.set(old_value, m_tracker.get_value(fd));
             #endif
 
+#if _EARLY_PRUNE_
+            double r = incremental_score_prune(g, fd, temp);
+#else
             double r = incremental_score(g, fd, temp);
-        
+#endif   
             #ifdef Z3DEBUG
             TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
                                         " --> " << r << std::endl; );
@@ -214,6 +346,22 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(old_value);
             #endif
 
+//            if (r >= best_score) {
+            if (r > best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+		// same as what_if, but only applied to the score of a specific atom, not the total score
+        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+            m_evaluator.update(fd, temp);
+			double r = m_tracker.get_score(e);
             if (r >= best_score) {
                 best_score = r;
                 best_const = fd_inx;            
@@ -224,7 +372,35 @@ class sls_tactic : public tactic {
             return false;
         }
 
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.add(old_value, add_value, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+			m_mpz_manager.del(temp);
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(mask2);
+
+		}
+
+		// Andreas: do we really need all those temporary mpzs?
+		void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.mul(old_value, m_two, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+			m_mpz_manager.del(temp);
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(mask2);
+        }
+
+        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            m_mpz_manager.div(old_value, m_two, result);
+        }
+
+		void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
             unsigned shift;        
             m_mpz_manager.add(old_value, m_one, incremented);
             if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
@@ -261,59 +437,73 @@ class sls_tactic : public tactic {
 
         void mk_random_move(goal_ref const & g) {
             unsigned rnd_mv = 0;
-            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-            move_type mt = (move_type) rnd_mv;
-
-            // inversion doesn't make sense, let's do a flip instead.
-            if (mt == MV_INV) mt = MV_FLIP;
+			if (m_stats.m_moves > 10000)
+				rnd_mv = 0;
 
 			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
-            mpz new_value;
-            unsigned bit = 0;
 
-            switch (mt)
-            {
-            case MV_FLIP: {
-                unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range());
-                bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                break;
-            }
-            case MV_INC: 
-                mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            case MV_DEC: 
-                mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            case MV_INV:
-                mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            default:
-                NOT_IMPLEMENTED_YET();
-            }
+			mpz new_value;
 
-            m_evaluator.update(fd, new_value);            
+			sort * srt = fd->get_range();
+            if (m_manager.is_bool(srt))
+				m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+			else
+			{
+#if _USE_ADDSUB_
+	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+				move_type mt = (move_type) rnd_mv;
 
-            TRACE("sls", tout << "Randomization candidates: ";
-                         for (unsigned i = 0; i < unsat_constants.size(); i++)
-                             tout << unsat_constants[i]->get_name() << ", ";
-                         tout << std::endl;
-                         tout << "Random move: ";
-                         switch (mt) {
-                         case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                         case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                         case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                         case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                         }
-                         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+				// inversion doesn't make sense, let's do a flip instead.
+				if (mt == MV_INV) mt = MV_FLIP;
+#else
+				mt = MV_FLIP;
+#endif
+				unsigned bit = 0;
 
-            m_mpz_manager.del(new_value);
-        }
+				switch (mt)
+				{
+					case MV_FLIP: {
+					unsigned bv_sz = m_bv_util.get_bv_size(srt);
+					bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+					mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+					break;
+				}
+				case MV_INC: 
+					mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				case MV_DEC: 
+					mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				case MV_INV:
+					mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				default:
+					NOT_IMPLEMENTED_YET();
+				}
 
+				TRACE("sls", tout << "Randomization candidates: ";
+							 for (unsigned i = 0; i < unsat_constants.size(); i++)
+								 tout << unsat_constants[i]->get_name() << ", ";
+							 tout << std::endl;
+							 tout << "Random move: ";
+							 switch (mt) {
+							 case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+							 case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+							 case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+							 case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+							 }
+							 tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+			}
+
+			m_evaluator.update(fd, new_value);            
+			m_mpz_manager.del(new_value);
+		}
+
+		// will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -359,6 +549,7 @@ class sls_tactic : public tactic {
                 SASSERT(check == score);
             }
 
+			// we can either check the condition once in the beginning or check it repeatedly after every bit
 #if _VNS_ == 1
 			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
 #else
@@ -390,9 +581,13 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
+		// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+			mpz temp2;
+#endif
             unsigned bv_sz;
             double new_score = score;
 
@@ -403,8 +598,12 @@ class sls_tactic : public tactic {
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-                    // What would happen if we flipped bit #i ?                
+#if _SKIP_BITS_
+				for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+#else
+				for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+					// What would happen if we flipped bit #i ?                
                     mk_flip(srt, old_value, j, temp);                
 
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
@@ -414,7 +613,8 @@ class sls_tactic : public tactic {
                 }
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
+#if _USE_ADDSUB_
+					if (!m_mpz_manager.is_even(old_value)) { 
                         // for odd values, try +1
                         mk_inc(bv_sz, old_value, temp);
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
@@ -426,16 +626,99 @@ class sls_tactic : public tactic {
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                             move = MV_DEC;
                     }
-
+#endif
                     // try inverting
                     mk_inv(bv_sz, old_value, temp);
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                         move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+                    mk_inc(bv_sz, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+                    // try multiplication by 2
+                    mk_mul2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_MUL2;
+
+#if _USE_MUL3_
+                    // try multiplication by 3
+                    mk_add(bv_sz, old_value, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_MUL3;
+#endif
+
+                    // try division by 2
+                    mk_div2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_DIV2;
+#endif
                 }
 
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
+				// Andreas: does not hold anymore now that we use top level score caching
+                //SASSERT(check == score);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+#if _USE_MUL3_
+            m_mpz_manager.del(temp2);
+#endif
+			return new_score;
+        }        
+
+		// same as find_best_move but only considers the score of the current expression instead of the overall score
+		double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz;
+			double new_score = m_tracker.get_score(e);
+			// Andreas: tie breaking not implemented yet
+			// double tie_score = top_score(g);
+            for (unsigned i = 0; i < to_evaluate.size(); i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+                for (unsigned j = 0; j < bv_sz; j++) {
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+                }
+
+                // reset to what it was before
+	            m_evaluator.update(fd, old_value);
             }
 
             m_mpz_manager.del(old_value);
@@ -443,7 +726,150 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
-        lbool search(goal_ref const & g) {        
+		// first try of intensification ... does not seem to be efficient
+		bool handle_plateau(goal_ref const & g)
+		{
+			unsigned sz = g->size();
+#if _BFS_
+			unsigned pos = m_stats.m_moves % sz;
+#else
+			unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+			expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+	        if (!e)
+				return 0;
+
+			expr * q = m_tracker.get_unsat_expression(e);
+			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+			for (unsigned i = 0; i < to_evaluate.size(); i++)
+			{
+				m_tracker.get_value(to_evaluate[i]);
+				m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+			}            
+			unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+			for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+			{
+				// Andreas: Could be extended to use (best) score but this is computationally more expensive.
+                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
+
+                if (new_const == static_cast<unsigned>(-1)) {
+					// Andreas: Actually this should never happen.
+					NOT_IMPLEMENTED_YET();
+                } else {
+                    m_stats.m_moves++;
+                    func_decl * fd = to_evaluate[new_const];
+
+                    switch (move) {
+                    case MV_FLIP: m_stats.m_flips++; break;
+                    case MV_INC: m_stats.m_incs++; break;
+                    case MV_DEC: m_stats.m_decs++; break;
+                    case MV_INV: m_stats.m_invs++; break;
+                    case MV_UMIN: m_stats.m_umins++; break;
+					case MV_MUL2: m_stats.m_mul2s++; break;
+					case MV_MUL3: m_stats.m_mul3s++; break;
+					case MV_DIV2: m_stats.m_div2s++; break;
+                    }
+                    
+					m_evaluator.update(fd, new_value);
+                }
+
+				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+					return 1;
+			}
+
+			for (unsigned i = 0; i < to_evaluate.size(); i++)
+				m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+
+			m_old_values.reset();
+
+			return 0;
+		}
+
+		// what_if version needed in the context of 2nd intensification try, combining local and global score
+        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
+                        double & best_score, mpz & best_value, unsigned i) {
+        
+            double global_score = incremental_score(g, fd, temp);
+			double local_score = m_tracker.get_score(e);
+            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+			if (new_score >= best_score) {
+                best_score = new_score;
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+		// find_best_move version needed in the context of 2nd intensification try
+        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+		{
+			mpz old_value, temp;
+            double best_score = 0;
+
+            sort * srt = fd->get_range();
+            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+			for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+                mk_flip(srt, old_value, j, temp);                
+                what_if(g, e, fd, temp, best_score, best_value, i); 
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+
+			return best_score;
+        }        
+
+		// second try to use intensification ... also not very effective
+		bool handle_plateau(goal_ref const & g, double old_score)
+		{
+			unsigned sz = g->size();
+#if _BFS_
+			unsigned new_const = m_stats.m_moves % sz;
+#else
+			unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+			expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+	        if (!e)
+				return 0;
+
+			expr * q = m_tracker.get_unsat_expression(e);
+			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+			new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+			func_decl * fd = to_evaluate[new_const];
+
+			mpz new_value;
+			//m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+			unsigned new_bit = 0;        
+			double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+			
+			for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+			{
+                new_score = find_best_move_local(g, q, fd, new_value, i);
+
+                m_stats.m_moves++;
+                m_stats.m_flips++;
+
+				global_score = incremental_score(g, fd, new_value);
+     			local_score = m_tracker.get_score(q);
+
+				SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+					return 1;
+			}
+
+			return 0;
+		}
+
+		// main search loop
+		lbool search(goal_ref const & g) {        
             lbool res = l_undef;
             double score = 0.0, old_score = 0.0;
             unsigned new_const = (unsigned)-1, new_bit = 0;        
@@ -463,16 +889,48 @@ class sls_tactic : public tactic {
 #if _RESTARTS_
 			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
+					if (m_stats.m_moves == 5590)
                     checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
             
+#if _TYPE_RSTEP_
+					if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+					{
+#if _TYPE_RSTEP_ == 1
+						m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+						mk_random_move(g);
+#endif
+                        score = top_score(g);
+
+	                    if (score >= 1.0) {
+	                        bool all_true = true;
+	                        for (unsigned i = 0; i < g->size() && all_true; i++)
+	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+	                                all_true=false;
+	                        if (all_true) {
+	                            res = l_true; // sat
+	                            goto bailout;
+							} else
+								TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+						}
+					}
+#endif
                     old_score = score;
                     new_const = (unsigned)-1;
                         
 					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-
+					if (!to_evaluate.size())
+					{
+						res = l_true;
+						goto bailout;
+					}
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
@@ -525,9 +983,17 @@ class sls_tactic : public tactic {
                         case MV_INC: m_stats.m_incs++; break;
                         case MV_DEC: m_stats.m_decs++; break;
                         case MV_INV: m_stats.m_invs++; break;
+                        case MV_UMIN: m_stats.m_umins++; break;
+						case MV_MUL2: m_stats.m_mul2s++; break;
+						case MV_MUL3: m_stats.m_mul3s++; break;
+						case MV_DIV2: m_stats.m_div2s++; break;
                         }
                     
-                        score = incremental_score(g, fd, new_value);    
+#if _REAL_RS_ || _REAL_PBFS_
+						score = serious_score(g, fd, new_value);
+#else
+						score = incremental_score(g, fd, new_value);    
+#endif
 
                         TRACE("sls", tout << "Score distribution:"; 
                                         for (unsigned i = 0; i < g->size(); i++)
@@ -535,9 +1001,10 @@ class sls_tactic : public tactic {
                                         tout << " TOP: " << score << std::endl; );                        
                     }
 
-                    if (score >= 1.0) {
+                    if (score >= 0.99999) {
+//                    if (score >= 1.0) {
                         // score could theoretically be imprecise.
-						// Andreas: Can it only be imprecise in one direction?
+						// Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -568,10 +1035,26 @@ class sls_tactic : public tactic {
 					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
                     //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
+#if _INTENSIFICATION_
+						handle_plateau(g, score);
+						//handle_plateau(g);
+#else
 						m_evaluator.randomize_local(g, m_stats.m_moves);
-                        //mk_random_move(g);
+#endif
+						//mk_random_move(g);
                         score = top_score(g);
-                    //}
+
+	                    if (score >= 1.0) {
+	                        bool all_true = true;
+	                        for (unsigned i = 0; i < g->size() && all_true; i++)
+	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+	                                all_true=false;
+	                        if (all_true) {
+	                            res = l_true; // sat
+	                            goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
                 }
             }
 
@@ -587,6 +1070,37 @@ class sls_tactic : public tactic {
                 return;
             }
 
+			verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+			verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+			verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+			verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+			verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+			verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+			verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+			verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+			verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+			verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+			verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+			verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+			verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+			verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+			verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+			verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+			verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+			verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+			verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+			verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+			verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+			verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+			verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+			verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+			verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+			verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+			verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+			
+#if _WEIGHT_DIST_ == 4
+					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
@@ -745,13 +1259,8 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-#if _CNF_
-						// Andreas: We will probably never use this. CNF sucks.
-                        mk_cnf_tactic(m, p));
-#else
 						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
-#endif
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 1061bd90e..b26912e5c 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -28,21 +28,32 @@ class sls_tracker {
     random_gen            m_rng;
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
-    mpz                   m_zero, m_one, m_two;   
+    mpz                   m_zero, m_one, m_two;
 	    
     struct value_score { 
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { };
+#if _EARLY_PRUNE_
+		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+#else
+		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
+#endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
+#if _EARLY_PRUNE_
+		double score_prune;
+		unsigned has_pos_occ;
+		unsigned has_neg_occ;
+#endif
         unsigned distance; // max distance from any root
+		unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
+			touched = other.touched;
             return *this;
         }
     };
@@ -60,6 +71,20 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
+#if _UCT_
+	unsigned              m_touched;
+#endif
+#if _REAL_RS_ || _REAL_PBFS_
+	ptr_vector<expr>	  m_unsat_expr;
+	obj_map<expr, unsigned>	m_where_false;
+	expr**					m_list_false;
+#endif
+#if _CACHE_TOP_SCORE_
+	double				  m_top_sum;
+#endif
+#if _WEIGHT_DIST_ == 4
+	double				  m_weight_dist_factor;
+#endif
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -79,6 +104,26 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+#if _WEIGHT_DIST_ == 4
+	inline void set_weight_dist_factor(double val) {
+		m_weight_dist_factor = val;
+	}
+#endif
+
+#if _CACHE_TOP_SCORE_
+	inline void adapt_top_sum(double add, double sub) {
+		m_top_sum += add - sub;
+	}
+
+	inline void set_top_sum(double new_score) {
+		m_top_sum = new_score;
+	}
+
+	inline double get_top_sum() {
+		return m_top_sum;
+	}
+#endif
+
     inline void set_value(expr * n, const mpz & r) {
         SASSERT(m_scores.contains(n));
         m_mpz_manager.set(m_scores.find(n).value, r);
@@ -123,6 +168,28 @@ public:
         return get_score(ep);
     }
 
+#if _EARLY_PRUNE_
+    inline void set_score_prune(expr * n, double score) {
+        SASSERT(m_scores.contains(n));
+        m_scores.find(n).score_prune = score;
+    }
+
+	inline double & get_score_prune(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).score_prune;
+    }
+
+	inline unsigned has_pos_occ(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).has_pos_occ;
+ 	}
+
+	inline unsigned has_neg_occ(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).has_neg_occ;
+ 	}
+#endif
+
     inline unsigned get_distance(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).distance;
@@ -297,7 +364,7 @@ public:
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
 			// Andreas: Maybe not fully correct.
-#if _FOCUS_ == 2
+#if _FOCUS_ == 2 || _INTENSIFICATION_
 			initialize_recursive(e);
 #endif
             ptr_vector<func_decl> t;
@@ -310,8 +377,57 @@ public:
         calculate_expr_distances(g);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
+
+#if _REAL_RS_ || _REAL_PBFS_
+		m_list_false = new expr*[sz];
+        for (unsigned i = 0; i < sz; i++)
+	  		if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+				break_assertion(g->form(i));
+#endif
+
+#if _EARLY_PRUNE_
+        for (unsigned i = 0; i < sz; i++)
+	  		setup_occs(g->form(i));
+#endif
+
+#if _UCT_
+		m_touched = 1;
+#endif
     }
 
+#if _REAL_RS_ || _REAL_PBFS_
+	void make_assertion(expr * e)
+	{
+		if (m_where_false.contains(e))
+		{
+			unsigned pos = m_where_false.find(e);
+			m_where_false.erase(e);
+			if (pos != m_where_false.size())
+			{
+				expr * q = m_list_false[m_where_false.size()];
+				m_list_false[pos] = q;
+				m_where_false.find(q) = pos;
+			}
+//			printf("Going in %d\n", m_where_false.size());
+		}
+		//if (m_unsat_expr.contains(e))
+			//m_unsat_expr.erase(e);
+	}
+
+	void break_assertion(expr * e)
+	{
+		if (!m_where_false.contains(e))
+		{
+			unsigned pos = m_where_false.size();
+			m_list_false[pos] = e;
+			m_where_false.insert(e, pos);
+	//		printf("Going in %d\n", m_where_false.size());
+		}
+		//if (!m_unsat_expr.contains(e))
+			//m_unsat_expr.push_back(e);
+	}
+#endif
+
     void show_model(std::ostream & out) {
         unsigned sz = get_num_constants();
         for (unsigned i = 0; i < sz; i++) {
@@ -420,10 +536,45 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
     }              
 
+#if _EARLY_PRUNE_
+	void setup_occs(expr * n, bool negated = false) {
+		if (m_manager.is_bool(n))
+		{
+			if (m_manager.is_and(n) || m_manager.is_or(n))
+			{
+	            SASSERT(!negated);
+	            app * a = to_app(n);
+	            expr * const * args = a->get_args();
+	            for (unsigned i = 0; i < a->get_num_args(); i++)
+					setup_occs(args[i]);
+			}
+			else if (m_manager.is_not(n))
+			{
+	            SASSERT(!negated);
+	            app * a = to_app(n);
+	            SASSERT(a->get_num_args() == 1);
+	            expr * child = a->get_arg(0);
+	            if (m_manager.is_and(child) || m_manager.is_or(child))
+	                NOT_IMPLEMENTED_YET();
+				setup_occs(child, true);
+			}
+			else
+			{
+				if (negated)
+					m_scores.find(n).has_neg_occ = 1;
+				else
+					m_scores.find(n).has_pos_occ = 1;
+			}
+		}
+        else
+            NOT_IMPLEMENTED_YET();
+    }
+#endif
+
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
-        double res = 0.0;
+		double res = 0.0;
             
         if (is_uninterp_const(n)) {
             const mpz & r = get_value(n);
@@ -488,7 +639,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-
+			
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -648,6 +799,7 @@ public:
 #if _WEIGHT_DIST_
 		app * a = to_app(n);
 		family_id afid = a->get_family_id();
+
 		if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
@@ -656,13 +808,14 @@ public:
 		res *= res;
 #elif _WEIGHT_DIST_ == 3
 		if (res < 1.0) res = 0.0;
+#elif _WEIGHT_DIST_ == 4
+		if (res < 1.0) res *= m_weight_dist_factor;
 #endif
 
-
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-
+	
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -708,6 +861,44 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
+	expr * get_unsat_expression(expr * e) {
+		if (m_manager.is_bool(e)) {
+			if (m_manager.is_and(e) || m_manager.is_or(e)) {
+				app * a = to_app(e);
+				expr * const * args = a->get_args();
+			    // Andreas: might be used for guided branching
+				//for (unsigned i = 0; i < a->get_num_args(); i++) {
+					//double cur = get_score(args[i]);
+				//}
+				// Andreas: A random number is better here since reusing flip will cause patterns.
+				unsigned int sz = a->get_num_args();
+				unsigned int pos = get_random_uint(16) % sz;
+				for (unsigned int i = pos; i < sz; i++) {
+	                expr * q = args[i];
+	                if (m_mpz_manager.neq(get_value(q), m_one))
+			            return get_unsat_expression(q);
+				}
+				for (unsigned int i = 0; i < pos; i++) {
+					expr * q = args[i];
+	                if (m_mpz_manager.neq(get_value(q), m_one))
+			            return get_unsat_expression(q);
+	            }
+	        }
+		}
+		return e;
+	}
+
+	ptr_vector<func_decl> & get_constants(expr * e) {
+        ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+        unsigned sz = this_decls.size();
+        for (unsigned i = 0; i < sz; i++) {
+            func_decl * fd = this_decls[i];
+            if (!m_temp_constants.contains(fd))
+                m_temp_constants.push_back(fd);
+        }
+        return m_temp_constants;
+	}
+
 	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
@@ -743,7 +934,6 @@ public:
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
 			if (!q)
 				return m_temp_constants;
-
 			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
@@ -754,6 +944,19 @@ public:
 	        return m_temp_constants;
 	}
 
+	ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
+			if (!e)
+				return m_temp_constants;
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz = this_decls.size();
+            for (unsigned j = 0; j < sz; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+	        return m_temp_constants;
+	}
+
 	ptr_vector<func_decl> & go_deeper(expr * e) {
 			if (m_manager.is_bool(e)) {
 				if (m_manager.is_and(e)) {
@@ -812,44 +1015,138 @@ public:
 		return go_deeper(q);
 	}
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+	ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
-            return get_constants();
+			if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+				return m_temp_constants;
+			else
+	            return get_constants();
         }
         else {
             m_temp_constants.reset();
 #if _FOCUS_ == 1
-#if _BFS_ == 3
-			unsigned int pos = 0;
-			double max = get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
+#if _UCT_
+			unsigned pos = -1;
+			value_score vscore;
+#if _PROBABILISTIC_UCT_
+			double sum_score = 0.0;
+			unsigned start_index = get_random_uint(16) % sz;
+			for (unsigned i = start_index; i < sz; i++)
+			{
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+					sum_score += q;
+					if (rand() <= (q * RAND_MAX / sum_score) + 1)
+						pos = i;
+				}	
+			}
+			for (unsigned i = 0; i < start_index; i++)
+			{
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+					sum_score += q;
+					if (rand() <= (q * RAND_MAX / sum_score) + 1)
+						pos = i;
+				}	
+			}
+#else
+			double max = -1.0;
+			for (unsigned i = 0; i < sz; i++) {
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+#if _UCT_ == 1
+				double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#elif _UCT_ == 2
+				double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#endif
+				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+            }
+#endif
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+
+#if _UCT_ == 1
+			m_scores.find(g->form(pos)).touched++;
+			m_touched++;
+#elif _UCT_ == 2
+			m_scores.find(g->form(pos)).touched = flip; 
+#endif
+			expr * e = g->form(pos);
+
+#elif _BFS_ == 3
+			unsigned int pos = -1;
+			double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
 				expr * e = g->form(i);
                 double q = get_score(e);
 				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
 #elif _BFS_ == 2
-			unsigned int pos = 0;
-			double min = get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
+			unsigned int pos = -1;
+			double min = 2.0;
+            for (unsigned i = 0; i < sz; i++) {
 				expr * e = g->form(i);
                 double q = get_score(e);
 				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
             }
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
 #elif _BFS_ == 1
-			unsigned int pos = flip % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = flip % m_constants.size();
+			unsigned int pos = flip % sz;
+			expr * e = get_unsat_assertion(g, sz, pos);
+#elif _UNIFORM_RANDOM_
+			unsigned cnt_unsat = 0, pos = -1;
+			for (unsigned i = 0; i < sz; i++)
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
+#elif _REAL_RS_
+			//unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+			//expr * e = get_unsat_assertion(g, sz, pos);
+			//expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+			sz = m_where_false.size();
+			if (sz == 0)
+				return m_temp_constants;
+			else
+				expr * e = m_list_false[get_random_uint(16) % sz];
+#elif _REAL_PBFS_
+			//unsigned pos = m_false_list[flip % m_cnt_false];
+			//expr * e = get_unsat_assertion(g, sz, pos);
+			//expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+			sz = m_where_false.size();
+			if (sz == 0)
+				return m_temp_constants;
+			else
+				expr * e = m_list_false[flip % sz];
 #else
-			unsigned int pos = get_random_uint(16) % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = get_random_uint(16) % m_constants.size();
+			unsigned int pos = get_random_uint(16) % sz;
+			expr * e = get_unsat_assertion(g, sz, pos);
 #endif
-			return get_unsat_constants_walksat(g, sz, pos);
+			return get_unsat_constants_walksat(e);
 #elif _FOCUS_ == 2
 #if _BFS_
-			unsigned int pos = flip % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = flip % m_constants.size();
+			unsigned int pos = flip % sz;
 #else
-			unsigned int pos = get_random_uint(16) % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = get_random_uint(16) % m_constants.size();
+			unsigned int pos = get_random_uint(16) % sz;
 #endif
 			return get_unsat_constants_crsat(g, sz, pos);
 #else
diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt
index 141193f76..fec38518d 100644
--- a/versions/z3-wsat-0.01.txt
+++ b/versions/z3-wsat-0.01.txt
@@ -9,4 +9,6 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
+
+BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt
index 2c0c0e7ad..8bcf2ffeb 100644
--- a/versions/z3-wsat-0.01b.txt
+++ b/versions/z3-wsat-0.01b.txt
@@ -9,4 +9,6 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
+
+BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file

From 5aa352fd16170df754cc8155e3b930cb452211b0 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 09:40:01 +0000
Subject: [PATCH 004/108] removed tabs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_evaluator.h | 268 ++++++-------
 src/tactic/sls/sls_tactic.cpp  | 572 ++++++++++++++--------------
 src/tactic/sls/sls_tracker.h   | 672 ++++++++++++++++-----------------
 3 files changed, 756 insertions(+), 756 deletions(-)

diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index eec9524a9..cdb08038f 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -528,7 +528,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -542,33 +542,33 @@ public:
                 m_tracker.set_value(cur, new_value);
 
 #if _REAL_RS_ || _REAL_PBFS_
-				if (!m_tracker.has_uplinks(cur))
-				{
-					if (m_mpz_manager.eq(new_value,m_one))
-						m_tracker.make_assertion(cur);
-					else
-						m_tracker.break_assertion(cur);
-				}
+                if (!m_tracker.has_uplinks(cur))
+                {
+                    if (m_mpz_manager.eq(new_value,m_one))
+                        m_tracker.make_assertion(cur);
+                    else
+                        m_tracker.break_assertion(cur);
+                }
 #endif
 
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -596,7 +596,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -609,23 +609,23 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -661,7 +661,7 @@ public:
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
 #if _REAL_RS_ || _REAL_PBFS_
-		run_serious_update(max_depth);
+        run_serious_update(max_depth);
 #else
         run_update(max_depth);
 #endif
@@ -693,27 +693,27 @@ public:
     unsigned run_update_bool_prune(unsigned cur_depth) {
         expr_fast_mark1 visited;
 
-		double prune_score, new_score;
-		unsigned pot_benefits = 0;
- 		SASSERT(cur_depth < m_traversal_stack_bool.size());
+        double prune_score, new_score;
+        unsigned pot_benefits = 0;
+         SASSERT(cur_depth < m_traversal_stack_bool.size());
  
         ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
 
         for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
             expr * cur = cur_depth_exprs[i];
 
-			new_score = m_tracker.score(cur); 
+            new_score = m_tracker.score(cur); 
 #if _CACHE_TOP_SCORE_
-			if (!m_tracker.has_uplinks(cur))
-				m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+            if (!m_tracker.has_uplinks(cur))
+                m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-			prune_score = m_tracker.get_score_prune(cur);
+            prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
-			if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
-				pot_benefits = 1;
-			if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
-				pot_benefits = 1;
+            if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+                pot_benefits = 1;
+            if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+                pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
                 ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -722,54 +722,54 @@ public:
                     unsigned next_d = m_tracker.get_distance(next);
                     SASSERT(next_d < cur_depth);
                     if (!visited.is_marked(next)) {
-						m_traversal_stack_bool[next_d].push_back(next);
+                        m_traversal_stack_bool[next_d].push_back(next);
                         visited.mark(next);
                     }
                 }
             }
-			else
-			{
-			}
-		}
+            else
+            {
+            }
+        }
 
-		cur_depth_exprs.reset();
+        cur_depth_exprs.reset();
         cur_depth--;
  
-		while (cur_depth != static_cast<unsigned>(-1)) {
-			ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-			if (pot_benefits)
-			{
-				unsigned cur_size = cur_depth_exprs.size();
-				for (unsigned i = 0; i < cur_size; i++) {
-					expr * cur = cur_depth_exprs[i];
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+            if (pot_benefits)
+            {
+                unsigned cur_size = cur_depth_exprs.size();
+                for (unsigned i = 0; i < cur_size; i++) {
+                    expr * cur = cur_depth_exprs[i];
 
 #if _CACHE_TOP_SCORE_
-					new_score = m_tracker.score(cur); 
-					if (!m_tracker.has_uplinks(cur))
-						m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-					m_tracker.set_score(cur, new_score);
+                    new_score = m_tracker.score(cur); 
+                    if (!m_tracker.has_uplinks(cur))
+                        m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.set_score(cur, new_score);
 #else
-					m_tracker.set_score(cur, m_tracker.score(cur));
+                    m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-					if (m_tracker.has_uplinks(cur)) {
-						ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-						for (unsigned j = 0; j < ups.size(); j++) {
-							expr * next = ups[j];
-							unsigned next_d = m_tracker.get_distance(next);
-							SASSERT(next_d < cur_depth);
-							if (!visited.is_marked(next)) {
-								m_traversal_stack_bool[next_d].push_back(next);
-								visited.mark(next);
-							}
-						}
-					}
-				}
-			}
-			cur_depth_exprs.reset();
-			cur_depth--;
-		}
+                    if (m_tracker.has_uplinks(cur)) {
+                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                        for (unsigned j = 0; j < ups.size(); j++) {
+                            expr * next = ups[j];
+                            unsigned next_d = m_tracker.get_distance(next);
+                            SASSERT(next_d < cur_depth);
+                            if (!visited.is_marked(next)) {
+                                m_traversal_stack_bool[next_d].push_back(next);
+                                visited.mark(next);
+                            }
+                        }
+                    }
+                }
+            }
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
 
-		return pot_benefits;
+        return pot_benefits;
     }
 
     void run_update_prune(unsigned max_depth) {
@@ -777,7 +777,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-		unsigned cur_depth = max_depth;
+        unsigned cur_depth = max_depth;
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -787,7 +787,7 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-				// should always have uplinks ...
+                // should always have uplinks ...
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -795,10 +795,10 @@ public:
                         unsigned next_d = m_tracker.get_distance(next);
                         SASSERT(next_d < cur_depth);
                         if (!visited.is_marked(next)) {
-							if (m_manager.is_bool(next))
-								m_traversal_stack_bool[max_depth].push_back(next);
-							else
-								m_traversal_stack[next_d].push_back(next);
+                            if (m_manager.is_bool(next))
+                                m_traversal_stack_bool[max_depth].push_back(next);
+                            else
+                                m_traversal_stack[next_d].push_back(next);
                             visited.mark(next);
                         }
                     }
@@ -817,23 +817,23 @@ public:
         expr * ep = m_tracker.get_entry_point(fd);
         unsigned cur_depth = m_tracker.get_distance(ep);
 
-		if (m_traversal_stack_bool.size() <= cur_depth)
+        if (m_traversal_stack_bool.size() <= cur_depth)
             m_traversal_stack_bool.resize(cur_depth+1);
-		if (m_traversal_stack.size() <= cur_depth) 
-				m_traversal_stack.resize(cur_depth+1);
+        if (m_traversal_stack.size() <= cur_depth) 
+                m_traversal_stack.resize(cur_depth+1);
 
-		if (m_manager.is_bool(ep))
-	        m_traversal_stack_bool[cur_depth].push_back(ep);
-		else
-		{
-	        m_traversal_stack[cur_depth].push_back(ep);
-			run_update_prune(cur_depth);
-		}
-		return run_update_bool_prune(cur_depth);
+        if (m_manager.is_bool(ep))
+            m_traversal_stack_bool[cur_depth].push_back(ep);
+        else
+        {
+            m_traversal_stack[cur_depth].push_back(ep);
+            run_update_prune(cur_depth);
+        }
+        return run_update_bool_prune(cur_depth);
     }
 #endif
 
-	void randomize_local(expr * e, unsigned int flip) {
+    void randomize_local(expr * e, unsigned int flip) {
         ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
 
         // Randomize _one_ candidate:
@@ -841,30 +841,30 @@ public:
         func_decl * fd = unsat_constants[r];
 #if _PERC_CHANGE_
         sort * srt = fd->get_range();
-		mpz temp;
+        mpz temp;
 
-		if (m_manager.is_bool(srt))
+        if (m_manager.is_bool(srt))
             m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
+        else
         {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+            mpz temp2, mask;
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(temp, m_tracker.get_value(fd));
 
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
+            for (unsigned bit = 0; bit < bv_sz; bit++)
+                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+                {
+                    m_mpz_manager.set(mask, m_powers(bit));
+                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
+                    m_mpz_manager.set(temp, temp2);
+                }
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(temp2);
+        }
 #else
-		mpz temp = m_tracker.get_random(fd->get_range());
+        mpz temp = m_tracker.get_random(fd->get_range());
 #endif
-		update(fd, temp);
+        update(fd, temp);
         m_mpz_manager.del(temp);
     } 
 
@@ -889,34 +889,34 @@ public:
         func_decl * fd = unsat_constants[r];
 #if _PERC_CHANGE_
         sort * srt = fd->get_range();
-		mpz temp;
+        mpz temp;
 
-		if (m_manager.is_bool(srt))
+        if (m_manager.is_bool(srt))
             m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
+        else
         {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+            mpz temp2, mask;
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(temp, m_tracker.get_value(fd));
 
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
+            for (unsigned bit = 0; bit < bv_sz; bit++)
+                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+                {
+                    m_mpz_manager.set(mask, m_powers(bit));
+                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
+                    m_mpz_manager.set(temp, temp2);
+                }
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(temp2);
+        }
 #else
-		mpz temp = m_tracker.get_random(fd->get_range());
+        mpz temp = m_tracker.get_random(fd->get_range());
 #endif
 
 #if _REAL_RS_ || _REAL_PBFS_
-		serious_update(fd, temp);
+        serious_update(fd, temp);
 #else
-		update(fd, temp);
+        update(fd, temp);
 #endif
         m_mpz_manager.del(temp);
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 3d5e3e438..fe871cefa 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -125,10 +125,10 @@ Notes:
 
 
 #if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
-	InvalidConfiguration;
+    InvalidConfiguration;
 #endif
 #if (_PROBABILISTIC_UCT_ && !_UCT_)
-	InvalidConfiguration;
+    InvalidConfiguration;
 #endif
 
 
@@ -150,10 +150,10 @@ class sls_tactic : public tactic {
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
-			m_umins(0),
-			m_mul2s(0),
-			m_mul3s(0),
-			m_div2s(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -183,8 +183,8 @@ class sls_tactic : public tactic {
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
-		ptr_vector<mpz> m_old_values;
-		
+        ptr_vector<mpz> m_old_values;
+        
         typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
 
         imp(ast_manager & m, params_ref const & p, stats & s) : 
@@ -267,18 +267,18 @@ class sls_tactic : public tactic {
             #else
             double top_sum = 0.0;
             unsigned sz = g->size();
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
                 top_sum += m_tracker.get_score(e);
             }
 
-			TRACE("sls_top", tout << "Score distribution:"; 
+            TRACE("sls_top", tout << "Score distribution:"; 
                                     for (unsigned i = 0; i < sz; i++)
                                         tout << " " << m_tracker.get_score(g->form(i));
                                     tout << " AVG: " << top_sum / (double) sz << std::endl; );
 
 #if _CACHE_TOP_SCORE_
-			m_tracker.set_top_sum(top_sum);
+            m_tracker.set_top_sum(top_sum);
 #endif
 
             return top_sum / (double) sz;
@@ -292,20 +292,20 @@ class sls_tactic : public tactic {
         }
 
         double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.serious_update(fd, new_value);
+            m_evaluator.serious_update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
         }
 
         double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.update(fd, new_value);
+            m_evaluator.update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
@@ -314,18 +314,18 @@ class sls_tactic : public tactic {
 #if _EARLY_PRUNE_
         double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
             m_stats.m_incr_evals++;
-			if (m_evaluator.update_prune(fd, new_value))
+            if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-				return (m_tracker.get_top_sum() / g->size());
+                return (m_tracker.get_top_sum() / g->size());
 #else
-	            return top_score(g);
+                return top_score(g);
 #endif
-			else
-				return 0.0;
+            else
+                return 0.0;
         }
 #endif
 
-		// checks whether the score outcome of a given move is better than the previous score
+        // checks whether the score outcome of a given move is better than the previous score
         bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
 
@@ -357,11 +357,11 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// same as what_if, but only applied to the score of a specific atom, not the total score
+        // same as what_if, but only applied to the score of a specific atom, not the total score
         bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
             m_evaluator.update(fd, temp);
-			double r = m_tracker.get_score(e);
+            double r = m_tracker.get_score(e);
             if (r >= best_score) {
                 best_score = r;
                 best_const = fd_inx;            
@@ -378,29 +378,29 @@ class sls_tactic : public tactic {
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
 
-		}
+        }
 
-		// Andreas: do we really need all those temporary mpzs?
-		void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+        // Andreas: do we really need all those temporary mpzs?
+        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             mpz temp, mask, mask2;
             m_mpz_manager.mul(old_value, m_two, temp);
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
         }
 
         void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             m_mpz_manager.div(old_value, m_two, result);
         }
 
-		void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
             unsigned shift;        
             m_mpz_manager.add(old_value, m_one, incremented);
             if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
@@ -437,73 +437,73 @@ class sls_tactic : public tactic {
 
         void mk_random_move(goal_ref const & g) {
             unsigned rnd_mv = 0;
-			if (m_stats.m_moves > 10000)
-				rnd_mv = 0;
+            if (m_stats.m_moves > 10000)
+                rnd_mv = 0;
 
-			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
+            ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
 
-			mpz new_value;
+            mpz new_value;
 
-			sort * srt = fd->get_range();
+            sort * srt = fd->get_range();
             if (m_manager.is_bool(srt))
-				m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-			else
-			{
+                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+            else
+            {
 #if _USE_ADDSUB_
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-				move_type mt = (move_type) rnd_mv;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+                move_type mt = (move_type) rnd_mv;
 
-				// inversion doesn't make sense, let's do a flip instead.
-				if (mt == MV_INV) mt = MV_FLIP;
+                // inversion doesn't make sense, let's do a flip instead.
+                if (mt == MV_INV) mt = MV_FLIP;
 #else
-				mt = MV_FLIP;
+                mt = MV_FLIP;
 #endif
-				unsigned bit = 0;
+                unsigned bit = 0;
 
-				switch (mt)
-				{
-					case MV_FLIP: {
-					unsigned bv_sz = m_bv_util.get_bv_size(srt);
-					bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-					mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-					break;
-				}
-				case MV_INC: 
-					mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_DEC: 
-					mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_INV:
-					mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				default:
-					NOT_IMPLEMENTED_YET();
-				}
+                switch (mt)
+                {
+                    case MV_FLIP: {
+                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
+                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+                    break;
+                }
+                case MV_INC: 
+                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_DEC: 
+                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_INV:
+                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                default:
+                    NOT_IMPLEMENTED_YET();
+                }
 
-				TRACE("sls", tout << "Randomization candidates: ";
-							 for (unsigned i = 0; i < unsat_constants.size(); i++)
-								 tout << unsat_constants[i]->get_name() << ", ";
-							 tout << std::endl;
-							 tout << "Random move: ";
-							 switch (mt) {
-							 case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-							 case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-							 case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-							 case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-							 }
-							 tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-			}
+                TRACE("sls", tout << "Randomization candidates: ";
+                             for (unsigned i = 0; i < unsat_constants.size(); i++)
+                                 tout << unsat_constants[i]->get_name() << ", ";
+                             tout << std::endl;
+                             tout << "Random move: ";
+                             switch (mt) {
+                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+                             }
+                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+            }
 
-			m_evaluator.update(fd, new_value);            
-			m_mpz_manager.del(new_value);
-		}
+            m_evaluator.update(fd, new_value);            
+            m_mpz_manager.del(new_value);
+        }
 
-		// will use VNS to ignore some possible moves and increase the flips per second
+        // will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -514,7 +514,7 @@ class sls_tactic : public tactic {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
                 bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-				if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -536,12 +536,12 @@ class sls_tactic : public tactic {
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                         move = MV_INV;
 
-					// try to flip lsb
-					mk_flip(srt, old_value, 0, temp);                
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = 0;
-	                    move = MV_FLIP;
-					}
+                    // try to flip lsb
+                    mk_flip(srt, old_value, 0, temp);                
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = 0;
+                        move = MV_FLIP;
+                    }
                 }
 
                 // reset to what it was before
@@ -549,12 +549,12 @@ class sls_tactic : public tactic {
                 SASSERT(check == score);
             }
 
-			// we can either check the condition once in the beginning or check it repeatedly after every bit
+            // we can either check the condition once in the beginning or check it repeatedly after every bit
 #if _VNS_ == 1
-			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
 #else
-			if (new_score <= score)
-			for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+            if (new_score <= score)
+            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
 #endif
             for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
                 func_decl * fd = to_evaluate[i];
@@ -563,30 +563,30 @@ class sls_tactic : public tactic {
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 // What would happen if we flipped bit #j ?                
-				if (j < bv_sz)
-				{
-					mk_flip(srt, old_value, j, temp);                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);                
 
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = j;
-	                    move = MV_FLIP;
-	                }
-				}
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
                 SASSERT(check == score);
             }
-			m_mpz_manager.del(old_value);
+            m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
             return new_score;
         }        
 
-		// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
-			mpz temp2;
+            mpz temp2;
 #endif
             unsigned bv_sz;
             double new_score = score;
@@ -599,11 +599,11 @@ class sls_tactic : public tactic {
 
                 // first try to flip every bit
 #if _SKIP_BITS_
-				for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
 #else
-				for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
 #endif
-					// What would happen if we flipped bit #i ?                
+                    // What would happen if we flipped bit #i ?                
                     mk_flip(srt, old_value, j, temp);                
 
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
@@ -614,7 +614,7 @@ class sls_tactic : public tactic {
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
 #if _USE_ADDSUB_
-					if (!m_mpz_manager.is_even(old_value)) { 
+                    if (!m_mpz_manager.is_even(old_value)) { 
                         // for odd values, try +1
                         mk_inc(bv_sz, old_value, temp);
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
@@ -660,7 +660,7 @@ class sls_tactic : public tactic {
 
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
-				// Andreas: does not hold anymore now that we use top level score caching
+                // Andreas: does not hold anymore now that we use top level score caching
                 //SASSERT(check == score);
             }
 
@@ -669,17 +669,17 @@ class sls_tactic : public tactic {
 #if _USE_MUL3_
             m_mpz_manager.del(temp2);
 #endif
-			return new_score;
+            return new_score;
         }        
 
-		// same as find_best_move but only considers the score of the current expression instead of the overall score
-		double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+        // same as find_best_move but only considers the score of the current expression instead of the overall score
+        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
             unsigned bv_sz;
-			double new_score = m_tracker.get_score(e);
-			// Andreas: tie breaking not implemented yet
-			// double tie_score = top_score(g);
+            double new_score = m_tracker.get_score(e);
+            // Andreas: tie breaking not implemented yet
+            // double tie_score = top_score(g);
             for (unsigned i = 0; i < to_evaluate.size(); i++) {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
@@ -718,7 +718,7 @@ class sls_tactic : public tactic {
                 }
 
                 // reset to what it was before
-	            m_evaluator.update(fd, old_value);
+                m_evaluator.update(fd, old_value);
             }
 
             m_mpz_manager.del(old_value);
@@ -726,37 +726,37 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
-		// first try of intensification ... does not seem to be efficient
-		bool handle_plateau(goal_ref const & g)
-		{
-			unsigned sz = g->size();
+        // first try of intensification ... does not seem to be efficient
+        bool handle_plateau(goal_ref const & g)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned pos = m_stats.m_moves % sz;
+            unsigned pos = m_stats.m_moves % sz;
 #else
-			unsigned pos = m_tracker.get_random_uint(16) % sz;
+            unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-			{
-				m_tracker.get_value(to_evaluate[i]);
-				m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-			}            
-			unsigned new_const = (unsigned)-1, new_bit = 0;        
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+            {
+                m_tracker.get_value(to_evaluate[i]);
+                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+            }            
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
             mpz new_value;
             move_type move;
-			for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-			{
-				// Andreas: Could be extended to use (best) score but this is computationally more expensive.
+            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+            {
+                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
                 find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
 
                 if (new_const == static_cast<unsigned>(-1)) {
-					// Andreas: Actually this should never happen.
-					NOT_IMPLEMENTED_YET();
+                    // Andreas: Actually this should never happen.
+                    NOT_IMPLEMENTED_YET();
                 } else {
                     m_stats.m_moves++;
                     func_decl * fd = to_evaluate[new_const];
@@ -767,35 +767,35 @@ class sls_tactic : public tactic {
                     case MV_DEC: m_stats.m_decs++; break;
                     case MV_INV: m_stats.m_invs++; break;
                     case MV_UMIN: m_stats.m_umins++; break;
-					case MV_MUL2: m_stats.m_mul2s++; break;
-					case MV_MUL3: m_stats.m_mul3s++; break;
-					case MV_DIV2: m_stats.m_div2s++; break;
+                    case MV_MUL2: m_stats.m_mul2s++; break;
+                    case MV_MUL3: m_stats.m_mul3s++; break;
+                    case MV_DIV2: m_stats.m_div2s++; break;
                     }
                     
-					m_evaluator.update(fd, new_value);
+                    m_evaluator.update(fd, new_value);
                 }
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-				m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
 
-			m_old_values.reset();
+            m_old_values.reset();
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// what_if version needed in the context of 2nd intensification try, combining local and global score
+        // what_if version needed in the context of 2nd intensification try, combining local and global score
         bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
                         double & best_score, mpz & best_value, unsigned i) {
         
             double global_score = incremental_score(g, fd, temp);
-			double local_score = m_tracker.get_score(e);
+            double local_score = m_tracker.get_score(e);
             double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
-			if (new_score >= best_score) {
+            if (new_score >= best_score) {
                 best_score = new_score;
                 m_mpz_manager.set(best_value, temp);
                 return true;
@@ -804,17 +804,17 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// find_best_move version needed in the context of 2nd intensification try
+        // find_best_move version needed in the context of 2nd intensification try
         double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-		{
-			mpz old_value, temp;
+        {
+            mpz old_value, temp;
             double best_score = 0;
 
             sort * srt = fd->get_range();
             unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
             m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
-			for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
                 mk_flip(srt, old_value, j, temp);                
                 what_if(g, e, fd, temp, best_score, best_value, i); 
             }
@@ -822,54 +822,54 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
 
-			return best_score;
+            return best_score;
         }        
 
-		// second try to use intensification ... also not very effective
-		bool handle_plateau(goal_ref const & g, double old_score)
-		{
-			unsigned sz = g->size();
+        // second try to use intensification ... also not very effective
+        bool handle_plateau(goal_ref const & g, double old_score)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned new_const = m_stats.m_moves % sz;
+            unsigned new_const = m_stats.m_moves % sz;
 #else
-			unsigned new_const = m_tracker.get_random_uint(16) % sz;
+            unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
 
-			new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-			func_decl * fd = to_evaluate[new_const];
+            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+            func_decl * fd = to_evaluate[new_const];
 
-			mpz new_value;
-			//m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-			unsigned new_bit = 0;        
-			double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-			
-			for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-			{
+            mpz new_value;
+            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+            unsigned new_bit = 0;        
+            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+            
+            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+            {
                 new_score = find_best_move_local(g, q, fd, new_value, i);
 
                 m_stats.m_moves++;
                 m_stats.m_flips++;
 
-				global_score = incremental_score(g, fd, new_value);
-     			local_score = m_tracker.get_score(q);
+                global_score = incremental_score(g, fd, new_value);
+                 local_score = m_tracker.get_score(q);
 
-				SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// main search loop
-		lbool search(goal_ref const & g) {        
+        // main search loop
+        lbool search(goal_ref const & g) {        
             lbool res = l_undef;
             double score = 0.0, old_score = 0.0;
             unsigned new_const = (unsigned)-1, new_bit = 0;        
@@ -885,52 +885,52 @@ class sls_tactic : public tactic {
         
             unsigned plateau_cnt = 0;
 
-			// Andreas: Why do we only allow so few plateaus?
+            // Andreas: Why do we only allow so few plateaus?
 #if _RESTARTS_
-			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+            while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
-					if (m_stats.m_moves == 5590)
+                    if (m_stats.m_moves == 5590)
                     checkpoint();
 
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
 #endif
             
 #if _TYPE_RSTEP_
-					if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-					{
+                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                    {
 #if _TYPE_RSTEP_ == 1
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #elif _TYPE_RSTEP_ == 2
-						mk_random_move(g);
+                        mk_random_move(g);
 #endif
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
-							} else
-								TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-						}
-					}
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                            } else
+                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                        }
+                    }
 #endif
                     old_score = score;
                     new_const = (unsigned)-1;
                         
-					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-					if (!to_evaluate.size())
-					{
-						res = l_true;
-						goto bailout;
-					}
+                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+                    if (!to_evaluate.size())
+                    {
+                        res = l_true;
+                        goto bailout;
+                    }
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
@@ -952,11 +952,11 @@ class sls_tactic : public tactic {
                                         for (unsigned i = 0; i < g->size(); i++)
                                             tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
                                             m_tracker.get_score(g->form(i)) << std::endl; );
-						// Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                         score = old_score;
                     }
                     else {
-						// Andreas: Why does randomizing not count as a move? (Now it does.)
+                        // Andreas: Why does randomizing not count as a move? (Now it does.)
                         m_stats.m_moves++;
                         func_decl * fd = to_evaluate[new_const];
 
@@ -984,15 +984,15 @@ class sls_tactic : public tactic {
                         case MV_DEC: m_stats.m_decs++; break;
                         case MV_INV: m_stats.m_invs++; break;
                         case MV_UMIN: m_stats.m_umins++; break;
-						case MV_MUL2: m_stats.m_mul2s++; break;
-						case MV_MUL3: m_stats.m_mul3s++; break;
-						case MV_DIV2: m_stats.m_div2s++; break;
+                        case MV_MUL2: m_stats.m_mul2s++; break;
+                        case MV_MUL3: m_stats.m_mul3s++; break;
+                        case MV_DIV2: m_stats.m_div2s++; break;
                         }
                     
 #if _REAL_RS_ || _REAL_PBFS_
-						score = serious_score(g, fd, new_value);
+                        score = serious_score(g, fd, new_value);
 #else
-						score = incremental_score(g, fd, new_value);    
+                        score = incremental_score(g, fd, new_value);    
 #endif
 
                         TRACE("sls", tout << "Score distribution:"; 
@@ -1004,7 +1004,7 @@ class sls_tactic : public tactic {
                     if (score >= 0.99999) {
 //                    if (score >= 1.0) {
                         // score could theoretically be imprecise.
-						// Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -1015,43 +1015,43 @@ class sls_tactic : public tactic {
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
-					/*
-					if (m_stats.m_moves % 100 == 0)
-					{
-						verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-						verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-					}*/
+                    /*
+                    if (m_stats.m_moves % 100 == 0)
+                    {
+                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+                    }*/
                 }
                 while (score > old_score && res == l_undef);                
-				
-				// Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                
+                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
                 if (score != old_score) {
-					report_tactic_progress("This should not happen I guess.", plateau_cnt);
+                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
                     plateau_cnt = 0;
-				} else {
-					m_stats.m_moves++;
+                } else {
+                    m_stats.m_moves++;
                     plateau_cnt++;
-					//report_tactic_progress("Plateau.", plateau_cnt);
-					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //report_tactic_progress("Plateau.", plateau_cnt);
+                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
                     //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
 #if _INTENSIFICATION_
-						handle_plateau(g, score);
-						//handle_plateau(g);
+                        handle_plateau(g, score);
+                        //handle_plateau(g);
 #else
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #endif
-						//mk_random_move(g);
+                        //mk_random_move(g);
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
@@ -1070,43 +1070,43 @@ class sls_tactic : public tactic {
                 return;
             }
 
-			verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-			verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-			verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-			verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-			verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-			verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-			verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-			verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-			verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-			verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-			verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-			verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-			verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-			verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-			verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-			verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-			verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-			verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-			verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-			verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-			verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-			verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-			verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-			
+            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+            
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
 #endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
             do {
                 checkpoint();
-				// Andreas: I think restarts are too impotant to ignore 99% of them are happening...
+                // Andreas: I think restarts are too impotant to ignore 99% of them are happening...
                 //if ((m_stats.m_restarts % 100) == 0)                        
                     report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 
@@ -1115,12 +1115,12 @@ class sls_tactic : public tactic {
                 if (res == l_undef)
                     m_tracker.randomize();
             }
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
-			verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
 
             if (res == l_true) {    
-				report_tactic_progress("Number of flips:", m_stats.m_moves);
+                report_tactic_progress("Number of flips:", m_stats.m_moves);
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -1259,7 +1259,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
+                        // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index b26912e5c..006bbb888 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -29,31 +29,31 @@ class sls_tracker {
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
     mpz                   m_zero, m_one, m_two;
-	    
+        
     struct value_score { 
 #if _EARLY_PRUNE_
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
 #else
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
 #endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
 #if _EARLY_PRUNE_
-		double score_prune;
-		unsigned has_pos_occ;
-		unsigned has_neg_occ;
+        double score_prune;
+        unsigned has_pos_occ;
+        unsigned has_neg_occ;
 #endif
         unsigned distance; // max distance from any root
-		unsigned touched;
+        unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
-			touched = other.touched;
+            touched = other.touched;
             return *this;
         }
     };
@@ -72,18 +72,18 @@ private:
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
 #if _UCT_
-	unsigned              m_touched;
+    unsigned              m_touched;
 #endif
 #if _REAL_RS_ || _REAL_PBFS_
-	ptr_vector<expr>	  m_unsat_expr;
-	obj_map<expr, unsigned>	m_where_false;
-	expr**					m_list_false;
+    ptr_vector<expr>      m_unsat_expr;
+    obj_map<expr, unsigned>    m_where_false;
+    expr**                    m_list_false;
 #endif
 #if _CACHE_TOP_SCORE_
-	double				  m_top_sum;
+    double                  m_top_sum;
 #endif
 #if _WEIGHT_DIST_ == 4
-	double				  m_weight_dist_factor;
+    double                  m_weight_dist_factor;
 #endif
 
 public:    
@@ -105,23 +105,23 @@ public:
     }
 
 #if _WEIGHT_DIST_ == 4
-	inline void set_weight_dist_factor(double val) {
-		m_weight_dist_factor = val;
-	}
+    inline void set_weight_dist_factor(double val) {
+        m_weight_dist_factor = val;
+    }
 #endif
 
 #if _CACHE_TOP_SCORE_
-	inline void adapt_top_sum(double add, double sub) {
-		m_top_sum += add - sub;
-	}
+    inline void adapt_top_sum(double add, double sub) {
+        m_top_sum += add - sub;
+    }
 
-	inline void set_top_sum(double new_score) {
-		m_top_sum = new_score;
-	}
+    inline void set_top_sum(double new_score) {
+        m_top_sum = new_score;
+    }
 
-	inline double get_top_sum() {
-		return m_top_sum;
-	}
+    inline double get_top_sum() {
+        return m_top_sum;
+    }
 #endif
 
     inline void set_value(expr * n, const mpz & r) {
@@ -174,20 +174,20 @@ public:
         m_scores.find(n).score_prune = score;
     }
 
-	inline double & get_score_prune(expr * n) {
+    inline double & get_score_prune(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).score_prune;
     }
 
-	inline unsigned has_pos_occ(expr * n) {
+    inline unsigned has_pos_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_pos_occ;
- 	}
+     }
 
-	inline unsigned has_neg_occ(expr * n) {
+    inline unsigned has_neg_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
- 	}
+     }
 #endif
 
     inline unsigned get_distance(expr * n) {
@@ -316,45 +316,45 @@ public:
         }
     }
 
-	void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(proc, visited, q);
-			}
-		}
-		for_each_expr(proc, visited, e);
- 	}
+    void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(proc, visited, q);
+            }
+        }
+        for_each_expr(proc, visited, e);
+     }
 
-	void initialize_recursive(expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(q);
-			}
-		}
-		ptr_vector<func_decl> t;
+    void initialize_recursive(expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(q);
+            }
+        }
+        ptr_vector<func_decl> t;
         m_constants_occ.insert_if_not_there(e, t);
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
- 	}
+     }
 
-	void initialize(goal_ref const & g) {
+    void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2
-			initialize_recursive(proc, visited, e);
+            initialize_recursive(proc, visited, e);
 #endif
             for_each_expr(proc, visited, e);
         }
@@ -363,9 +363,9 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
-			initialize_recursive(e);
+            initialize_recursive(e);
 #endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
@@ -379,53 +379,53 @@ public:
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
 #if _REAL_RS_ || _REAL_PBFS_
-		m_list_false = new expr*[sz];
+        m_list_false = new expr*[sz];
         for (unsigned i = 0; i < sz; i++)
-	  		if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-				break_assertion(g->form(i));
+              if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+                break_assertion(g->form(i));
 #endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-	  		setup_occs(g->form(i));
+              setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-		m_touched = 1;
+        m_touched = 1;
 #endif
     }
 
 #if _REAL_RS_ || _REAL_PBFS_
-	void make_assertion(expr * e)
-	{
-		if (m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.find(e);
-			m_where_false.erase(e);
-			if (pos != m_where_false.size())
-			{
-				expr * q = m_list_false[m_where_false.size()];
-				m_list_false[pos] = q;
-				m_where_false.find(q) = pos;
-			}
-//			printf("Going in %d\n", m_where_false.size());
-		}
-		//if (m_unsat_expr.contains(e))
-			//m_unsat_expr.erase(e);
-	}
+    void make_assertion(expr * e)
+    {
+        if (m_where_false.contains(e))
+        {
+            unsigned pos = m_where_false.find(e);
+            m_where_false.erase(e);
+            if (pos != m_where_false.size())
+            {
+                expr * q = m_list_false[m_where_false.size()];
+                m_list_false[pos] = q;
+                m_where_false.find(q) = pos;
+            }
+//            printf("Going in %d\n", m_where_false.size());
+        }
+        //if (m_unsat_expr.contains(e))
+            //m_unsat_expr.erase(e);
+    }
 
-	void break_assertion(expr * e)
-	{
-		if (!m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.size();
-			m_list_false[pos] = e;
-			m_where_false.insert(e, pos);
-	//		printf("Going in %d\n", m_where_false.size());
-		}
-		//if (!m_unsat_expr.contains(e))
-			//m_unsat_expr.push_back(e);
-	}
+    void break_assertion(expr * e)
+    {
+        if (!m_where_false.contains(e))
+        {
+            unsigned pos = m_where_false.size();
+            m_list_false[pos] = e;
+            m_where_false.insert(e, pos);
+    //        printf("Going in %d\n", m_where_false.size());
+        }
+        //if (!m_unsat_expr.contains(e))
+            //m_unsat_expr.push_back(e);
+    }
 #endif
 
     void show_model(std::ostream & out) {
@@ -537,35 +537,35 @@ public:
     }              
 
 #if _EARLY_PRUNE_
-	void setup_occs(expr * n, bool negated = false) {
-		if (m_manager.is_bool(n))
-		{
-			if (m_manager.is_and(n) || m_manager.is_or(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            expr * const * args = a->get_args();
-	            for (unsigned i = 0; i < a->get_num_args(); i++)
-					setup_occs(args[i]);
-			}
-			else if (m_manager.is_not(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            SASSERT(a->get_num_args() == 1);
-	            expr * child = a->get_arg(0);
-	            if (m_manager.is_and(child) || m_manager.is_or(child))
-	                NOT_IMPLEMENTED_YET();
-				setup_occs(child, true);
-			}
-			else
-			{
-				if (negated)
-					m_scores.find(n).has_neg_occ = 1;
-				else
-					m_scores.find(n).has_pos_occ = 1;
-			}
-		}
+    void setup_occs(expr * n, bool negated = false) {
+        if (m_manager.is_bool(n))
+        {
+            if (m_manager.is_and(n) || m_manager.is_or(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                expr * const * args = a->get_args();
+                for (unsigned i = 0; i < a->get_num_args(); i++)
+                    setup_occs(args[i]);
+            }
+            else if (m_manager.is_not(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                SASSERT(a->get_num_args() == 1);
+                expr * child = a->get_arg(0);
+                if (m_manager.is_and(child) || m_manager.is_or(child))
+                    NOT_IMPLEMENTED_YET();
+                setup_occs(child, true);
+            }
+            else
+            {
+                if (negated)
+                    m_scores.find(n).has_neg_occ = 1;
+                else
+                    m_scores.find(n).has_pos_occ = 1;
+            }
+        }
         else
             NOT_IMPLEMENTED_YET();
     }
@@ -574,7 +574,7 @@ public:
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
-		double res = 0.0;
+        double res = 0.0;
             
         if (is_uninterp_const(n)) {
             const mpz & r = get_value(n);
@@ -587,14 +587,14 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it does not even occur.
+            // Andreas: Seems to have no effect. Probably it does not even occur.
 #if _SCORE_AND_AVG_
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
                 sum += get_score(args[i]);
             res = sum / (double) a->get_num_args();
 #else
-			double min = 1.0;
+            double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur < min) min = cur;
@@ -606,16 +606,16 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it is still too similar to the original version.
+            // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
 #if _SCORE_OR_MUL_
-			double inv = 1.0;
+            double inv = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 inv *= (1.0 - get_score(args[i]));
             }
             res = 1.0 - inv;
 #else
-			double max = 0.0;
+            double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur > max) max = cur;
@@ -639,7 +639,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-			
+            
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -701,7 +701,7 @@ public:
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
                     res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-					m_mpz_manager.del(diff);
+                    m_mpz_manager.del(diff);
                 }
             }
             else {
@@ -762,7 +762,7 @@ public:
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
-			m_mpz_manager.del(x);
+            m_mpz_manager.del(x);
             m_mpz_manager.del(y);                
         }
         else if (m_manager.is_not(n)) {                
@@ -797,25 +797,25 @@ public:
         SASSERT(res >= 0.0 && res <= 1.0);
 
 #if _WEIGHT_DIST_
-		app * a = to_app(n);
-		family_id afid = a->get_family_id();
+        app * a = to_app(n);
+        family_id afid = a->get_family_id();
 
-		if (afid == m_bv_util.get_family_id())
+        if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
-		if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+        if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
 #elif _WEIGHT_DIST_ == 2
-		res *= res;
+        res *= res;
 #elif _WEIGHT_DIST_ == 3
-		if (res < 1.0) res = 0.0;
+        if (res < 1.0) res = 0.0;
 #elif _WEIGHT_DIST_ == 4
-		if (res < 1.0) res *= m_weight_dist_factor;
+        if (res < 1.0) res *= m_weight_dist_factor;
 #endif
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-	
+    
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -861,34 +861,34 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-	expr * get_unsat_expression(expr * e) {
-		if (m_manager.is_bool(e)) {
-			if (m_manager.is_and(e) || m_manager.is_or(e)) {
-				app * a = to_app(e);
-				expr * const * args = a->get_args();
-			    // Andreas: might be used for guided branching
-				//for (unsigned i = 0; i < a->get_num_args(); i++) {
-					//double cur = get_score(args[i]);
-				//}
-				// Andreas: A random number is better here since reusing flip will cause patterns.
-				unsigned int sz = a->get_num_args();
-				unsigned int pos = get_random_uint(16) % sz;
-				for (unsigned int i = pos; i < sz; i++) {
-	                expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-				}
-				for (unsigned int i = 0; i < pos; i++) {
-					expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-	            }
-	        }
-		}
-		return e;
-	}
+    expr * get_unsat_expression(expr * e) {
+        if (m_manager.is_bool(e)) {
+            if (m_manager.is_and(e) || m_manager.is_or(e)) {
+                app * a = to_app(e);
+                expr * const * args = a->get_args();
+                // Andreas: might be used for guided branching
+                //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                    //double cur = get_score(args[i]);
+                //}
+                // Andreas: A random number is better here since reusing flip will cause patterns.
+                unsigned int sz = a->get_num_args();
+                unsigned int pos = get_random_uint(16) % sz;
+                for (unsigned int i = pos; i < sz; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+                for (unsigned int i = 0; i < pos; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+            }
+        }
+        return e;
+    }
 
-	ptr_vector<func_decl> & get_constants(expr * e) {
+    ptr_vector<func_decl> & get_constants(expr * e) {
         ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
         unsigned sz = this_decls.size();
         for (unsigned i = 0; i < sz; i++) {
@@ -897,9 +897,9 @@ public:
                 m_temp_constants.push_back(fd);
         }
         return m_temp_constants;
-	}
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
@@ -913,244 +913,244 @@ public:
             }
         }
         return m_temp_constants;
-	}
+    }
 
-	expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
-			for (unsigned i = pos; i < sz; i++) {
+    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+            for (unsigned i = pos; i < sz; i++) {
                 expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
-			}
-			for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
+                    return q;
             }
-			return 0;
-	}
+            for (unsigned i = 0; i < pos; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+                    return q;
+            }
+            return 0;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-			expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(g, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
-			if (!q)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            if (!q)
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
-			if (!e)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
+            if (!e)
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz = this_decls.size();
             for (unsigned j = 0; j < sz; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & go_deeper(expr * e) {
-			if (m_manager.is_bool(e)) {
-				if (m_manager.is_and(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-				    // Andreas: might be used for guided branching
-					//for (unsigned i = 0; i < a->get_num_args(); i++) {
-						//double cur = get_score(args[i]);
-					//}
-					// Andreas: A random number is better here since reusing flip will cause patterns.
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-				else if (m_manager.is_or(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-			}
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & go_deeper(expr * e) {
+            if (m_manager.is_bool(e)) {
+                if (m_manager.is_and(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    // Andreas: might be used for guided branching
+                    //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                        //double cur = get_score(args[i]);
+                    //}
+                    // Andreas: A random number is better here since reusing flip will cause patterns.
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+                else if (m_manager.is_or(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+            }
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-		expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(g, sz, pos);
         if (!q)
-			return m_temp_constants;
+            return m_temp_constants;
 
-		return go_deeper(q);
-	}
+        return go_deeper(q);
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
-			if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
-				return m_temp_constants;
-			else
-	            return get_constants();
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+                return m_temp_constants;
+            else
+                return get_constants();
         }
         else {
             m_temp_constants.reset();
 #if _FOCUS_ == 1
 #if _UCT_
-			unsigned pos = -1;
-			value_score vscore;
+            unsigned pos = -1;
+            value_score vscore;
 #if _PROBABILISTIC_UCT_
-			double sum_score = 0.0;
-			unsigned start_index = get_random_uint(16) % sz;
-			for (unsigned i = start_index; i < sz; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+            double sum_score = 0.0;
+            unsigned start_index = get_random_uint(16) % sz;
+            for (unsigned i = start_index; i < sz; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
-			for (unsigned i = 0; i < start_index; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }    
+            }
+            for (unsigned i = 0; i < start_index; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }    
+            }
 #else
-			double max = -1.0;
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+            double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
 #if _UCT_ == 1
-				double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
 #elif _UCT_ == 2
-				double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+                double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
 #endif
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
 
 #if _UCT_ == 1
-			m_scores.find(g->form(pos)).touched++;
-			m_touched++;
+            m_scores.find(g->form(pos)).touched++;
+            m_touched++;
 #elif _UCT_ == 2
-			m_scores.find(g->form(pos)).touched = flip; 
+            m_scores.find(g->form(pos)).touched = flip; 
 #endif
-			expr * e = g->form(pos);
+            expr * e = g->form(pos);
 
 #elif _BFS_ == 3
-			unsigned int pos = -1;
-			double max = -1.0;
+            unsigned int pos = -1;
+            double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 2
-			unsigned int pos = -1;
-			double min = 2.0;
+            unsigned int pos = -1;
+            double min = 2.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+                if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 1
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #elif _UNIFORM_RANDOM_
-			unsigned cnt_unsat = 0, pos = -1;
-			for (unsigned i = 0; i < sz; i++)
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            unsigned cnt_unsat = 0, pos = -1;
+            for (unsigned i = 0; i < sz; i++)
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;    
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _REAL_RS_
-			//unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[get_random_uint(16) % sz];
+            //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            else
+                expr * e = m_list_false[get_random_uint(16) % sz];
 #elif _REAL_PBFS_
-			//unsigned pos = m_false_list[flip % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[flip % sz];
+            //unsigned pos = m_false_list[flip % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            else
+                expr * e = m_list_false[flip % sz];
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #endif
-			return get_unsat_constants_walksat(e);
+            return get_unsat_constants_walksat(e);
 #elif _FOCUS_ == 2
 #if _BFS_
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
 #endif
-			return get_unsat_constants_crsat(g, sz, pos);
+            return get_unsat_constants_crsat(g, sz, pos);
 #else
-			return get_unsat_constants_gsat(g, sz);
+            return get_unsat_constants_gsat(g, sz);
 #endif
         }
     }

From 90245021b23f8402e13b4aa85f8ac5e629b7caf5 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Wed, 19 Mar 2014 11:49:44 +0000
Subject: [PATCH 005/108] Current version for relocating.

---
 src/tactic/sls/sls_evaluator.h | 298 +++++------
 src/tactic/sls/sls_tactic.cpp  | 842 ++++++++++++++++++-----------
 src/tactic/sls/sls_tracker.h   | 947 +++++++++++++++++++++------------
 3 files changed, 1290 insertions(+), 797 deletions(-)

diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index eec9524a9..696d7664a 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -78,7 +78,11 @@ public:
             case OP_AND: {
                 m_mpz_manager.set(result, m_one);
                 for (unsigned i = 0; i < n_args; i++)
+#if _DIRTY_UP_
+                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i]))  {
+#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result))  {
+#endif
                         m_mpz_manager.set(result, m_zero);
                         break;
                     }
@@ -86,7 +90,11 @@ public:
             }
             case OP_OR: {
                 for (unsigned i = 0; i < n_args; i++)
+#if _DIRTY_UP_
+                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i]))  {
+#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) {
+#endif
                         m_mpz_manager.set(result, m_one);
                         break;
                     }
@@ -94,9 +102,16 @@ public:
             }
             case OP_NOT: {
                 SASSERT(n_args == 1);
+#if _DIRTY_UP_
+                if (m_tracker.is_top_expr(args[0]))
+                    m_mpz_manager.set(result, m_zero);
+                else
+                    m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero);
+#else
                 const mpz & child = m_tracker.get_value(args[0]);
                 SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child));                
-                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);                
+                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);
+#endif
                 break;
             }
             case OP_EQ: {
@@ -528,7 +543,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -542,31 +557,34 @@ public:
                 m_tracker.set_value(cur, new_value);
 
 #if _REAL_RS_ || _REAL_PBFS_
-				if (!m_tracker.has_uplinks(cur))
-				{
-					if (m_mpz_manager.eq(new_value,m_one))
-						m_tracker.make_assertion(cur);
-					else
-						m_tracker.break_assertion(cur);
-				}
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
+                {
+                    if (m_mpz_manager.eq(new_value,m_one))
+                        m_tracker.make_assertion(cur);
+                    else
+                        m_tracker.break_assertion(cur);
+                }
 #endif
 
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
 #endif			
                 if (m_tracker.has_uplinks(cur)) {
@@ -596,7 +614,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -609,21 +627,23 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
 #endif			
                 if (m_tracker.has_uplinks(cur)) {
@@ -661,7 +681,7 @@ public:
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
 #if _REAL_RS_ || _REAL_PBFS_
-		run_serious_update(max_depth);
+        run_serious_update(max_depth);
 #else
         run_update(max_depth);
 #endif
@@ -693,27 +713,28 @@ public:
     unsigned run_update_bool_prune(unsigned cur_depth) {
         expr_fast_mark1 visited;
 
-		double prune_score, new_score;
-		unsigned pot_benefits = 0;
- 		SASSERT(cur_depth < m_traversal_stack_bool.size());
+        double prune_score, new_score;
+        unsigned pot_benefits = 0;
+        SASSERT(cur_depth < m_traversal_stack_bool.size());
  
         ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
 
         for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
             expr * cur = cur_depth_exprs[i];
 
-			new_score = m_tracker.score(cur); 
+            new_score = m_tracker.score(cur); 
 #if _CACHE_TOP_SCORE_
-			if (!m_tracker.has_uplinks(cur))
-				m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+            //if (!m_tracker.has_uplinks(cur))
+            if (m_tracker.is_top_expr(cur))
+                m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-			prune_score = m_tracker.get_score_prune(cur);
+            prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
-			if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
-				pot_benefits = 1;
-			if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
-				pot_benefits = 1;
+            if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+                pot_benefits = 1;
+            if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+                pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
                 ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -722,54 +743,55 @@ public:
                     unsigned next_d = m_tracker.get_distance(next);
                     SASSERT(next_d < cur_depth);
                     if (!visited.is_marked(next)) {
-						m_traversal_stack_bool[next_d].push_back(next);
+                        m_traversal_stack_bool[next_d].push_back(next);
                         visited.mark(next);
                     }
                 }
             }
-			else
-			{
-			}
-		}
+            else
+            {
+            }
+        }
 
-		cur_depth_exprs.reset();
+        cur_depth_exprs.reset();
         cur_depth--;
  
-		while (cur_depth != static_cast<unsigned>(-1)) {
-			ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-			if (pot_benefits)
-			{
-				unsigned cur_size = cur_depth_exprs.size();
-				for (unsigned i = 0; i < cur_size; i++) {
-					expr * cur = cur_depth_exprs[i];
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+            if (pot_benefits)
+            {
+                unsigned cur_size = cur_depth_exprs.size();
+                for (unsigned i = 0; i < cur_size; i++) {
+                    expr * cur = cur_depth_exprs[i];
 
 #if _CACHE_TOP_SCORE_
-					new_score = m_tracker.score(cur); 
-					if (!m_tracker.has_uplinks(cur))
-						m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-					m_tracker.set_score(cur, new_score);
+                    new_score = m_tracker.score(cur); 
+                    //if (!m_tracker.has_uplinks(cur))
+                    if (m_tracker.is_top_expr(cur))
+                        m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.set_score(cur, new_score);
 #else
-					m_tracker.set_score(cur, m_tracker.score(cur));
+                    m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-					if (m_tracker.has_uplinks(cur)) {
-						ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-						for (unsigned j = 0; j < ups.size(); j++) {
-							expr * next = ups[j];
-							unsigned next_d = m_tracker.get_distance(next);
-							SASSERT(next_d < cur_depth);
-							if (!visited.is_marked(next)) {
-								m_traversal_stack_bool[next_d].push_back(next);
-								visited.mark(next);
-							}
-						}
-					}
-				}
-			}
-			cur_depth_exprs.reset();
-			cur_depth--;
-		}
+                    if (m_tracker.has_uplinks(cur)) {
+                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                        for (unsigned j = 0; j < ups.size(); j++) {
+                            expr * next = ups[j];
+                            unsigned next_d = m_tracker.get_distance(next);
+                            SASSERT(next_d < cur_depth);
+                            if (!visited.is_marked(next)) {
+                                m_traversal_stack_bool[next_d].push_back(next);
+                                visited.mark(next);
+                            }
+                        }
+                    }
+                }
+            }
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
 
-		return pot_benefits;
+        return pot_benefits;
     }
 
     void run_update_prune(unsigned max_depth) {
@@ -777,7 +799,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-		unsigned cur_depth = max_depth;
+        unsigned cur_depth = max_depth;
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -787,7 +809,7 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-				// should always have uplinks ...
+                // should always have uplinks ...
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -795,10 +817,10 @@ public:
                         unsigned next_d = m_tracker.get_distance(next);
                         SASSERT(next_d < cur_depth);
                         if (!visited.is_marked(next)) {
-							if (m_manager.is_bool(next))
-								m_traversal_stack_bool[max_depth].push_back(next);
-							else
-								m_traversal_stack[next_d].push_back(next);
+                            if (m_manager.is_bool(next))
+                                m_traversal_stack_bool[max_depth].push_back(next);
+                            else
+                                m_traversal_stack[next_d].push_back(next);
                             visited.mark(next);
                         }
                     }
@@ -817,60 +839,23 @@ public:
         expr * ep = m_tracker.get_entry_point(fd);
         unsigned cur_depth = m_tracker.get_distance(ep);
 
-		if (m_traversal_stack_bool.size() <= cur_depth)
+        if (m_traversal_stack_bool.size() <= cur_depth)
             m_traversal_stack_bool.resize(cur_depth+1);
-		if (m_traversal_stack.size() <= cur_depth) 
-				m_traversal_stack.resize(cur_depth+1);
+        if (m_traversal_stack.size() <= cur_depth) 
+                m_traversal_stack.resize(cur_depth+1);
 
-		if (m_manager.is_bool(ep))
-	        m_traversal_stack_bool[cur_depth].push_back(ep);
-		else
-		{
-	        m_traversal_stack[cur_depth].push_back(ep);
-			run_update_prune(cur_depth);
-		}
-		return run_update_bool_prune(cur_depth);
+        if (m_manager.is_bool(ep))
+            m_traversal_stack_bool[cur_depth].push_back(ep);
+        else
+        {
+            m_traversal_stack[cur_depth].push_back(ep);
+            run_update_prune(cur_depth);
+        }
+        return run_update_bool_prune(cur_depth);
     }
 #endif
 
-	void randomize_local(expr * e, unsigned int flip) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
-
-        // Randomize _one_ candidate:
-        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
-        func_decl * fd = unsat_constants[r];
-#if _PERC_CHANGE_
-        sort * srt = fd->get_range();
-		mpz temp;
-
-		if (m_manager.is_bool(srt))
-            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
-        {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
-
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
-#else
-		mpz temp = m_tracker.get_random(fd->get_range());
-#endif
-		update(fd, temp);
-        m_mpz_manager.del(temp);
-    } 
-
-     void randomize_local(goal_ref const & g, unsigned int flip) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
-
+    void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _all_ candidates:
 
         //// bool did_something = false;
@@ -889,34 +874,34 @@ public:
         func_decl * fd = unsat_constants[r];
 #if _PERC_CHANGE_
         sort * srt = fd->get_range();
-		mpz temp;
+        mpz temp;
 
-		if (m_manager.is_bool(srt))
+        if (m_manager.is_bool(srt))
             m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
+        else
         {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+            mpz temp2, mask;
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(temp, m_tracker.get_value(fd));
 
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
+            for (unsigned bit = 0; bit < bv_sz; bit++)
+                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+                {
+                    m_mpz_manager.set(mask, m_powers(bit));
+                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
+                    m_mpz_manager.set(temp, temp2);
+                }
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(temp2);
+        }
 #else
-		mpz temp = m_tracker.get_random(fd->get_range());
+        mpz temp = m_tracker.get_random(fd->get_range());
 #endif
 
 #if _REAL_RS_ || _REAL_PBFS_
-		serious_update(fd, temp);
+        serious_update(fd, temp);
 #else
-		update(fd, temp);
+        update(fd, temp);
 #endif
         m_mpz_manager.del(temp);
 
@@ -927,6 +912,15 @@ public:
                         tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
                         tout << "Locally randomized model: " << std::endl; 
                         m_tracker.show_model(tout); );
+
+    }
+
+    void randomize_local(expr * e) {
+        randomize_local(m_tracker.get_constants(e));
+    } 
+
+     void randomize_local(goal_ref const & g, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(g, flip));
     } 
 };
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 3d5e3e438..ada0ec359 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -34,6 +34,8 @@ Notes:
 #include"propagate_values_tactic.h"
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
+#include"luby.h"
+#include "ctx_simplify_tactic.h"
 
 // which unsatisfied assertion is selected? only works with _FOCUS_ > 0
 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
@@ -43,9 +45,23 @@ Notes:
 // 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
 #define _FOCUS_ 1
 
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 0
+
 // do we use restarts?
-// 0 = no, otherwise the value defines the maximum number of moves
-#define _RESTARTS_ 0
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 3.0
 
 // timelimit
 #define _TIMELIMIT_ 3600
@@ -66,38 +82,58 @@ Notes:
 // 2 = yes, by squaring it
 // 3 = yes, by setting it to zero
 // 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 0
+#define _WEIGHT_DIST_ 1
 
 // the factor used for _WEIGHT_DIST_ = 1
 #define _WEIGHT_DIST_FACTOR_ 0.25
 
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
 // do we use intensification steps in local minima? if so, how many?
 #define _INTENSIFICATION_ 0
 #define _INTENSIFICATION_TRIES_ 0
 
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 0
+#define _UCT_ 1
 
 // how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 0.01
+#define _UCT_CONSTANT_ 10.0
 
 // is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
 #define _PROBABILISTIC_UCT_ 0
 
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 1
+
 // shall we use addition/subtraction?
 #define _USE_ADDSUB_ 1
 
 // shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 1
+#define _USE_MUL2DIV2_ 0
 
 // shall we try multiplication by 3?
-#define _USE_MUL3_ 1
+#define _USE_MUL3_ 0
 
 // shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 1
+#define _USE_UNARY_MINUS_ 0
 
 // is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 1
+#define _UNIFORM_RANDOM_ 0
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
@@ -124,13 +160,21 @@ Notes:
 #define _CACHE_TOP_SCORE_ 1
 
 
-#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
-	InvalidConfiguration;
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
+    InvalidConfiguration;
 #endif
 #if (_PROBABILISTIC_UCT_ && !_UCT_)
-	InvalidConfiguration;
+    InvalidConfiguration;
+#endif
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+    InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+    InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+    InvalidConfiguration;
 #endif
-
 
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
@@ -150,10 +194,10 @@ class sls_tactic : public tactic {
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
-			m_umins(0),
-			m_mul2s(0),
-			m_mul3s(0),
-			m_div2s(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -180,11 +224,12 @@ class sls_tactic : public tactic {
         sls_tracker     m_tracker;
         sls_evaluator   m_evaluator;
 
+        unsigned		m_restart_limit;
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
-		ptr_vector<mpz> m_old_values;
-		
+        ptr_vector<mpz> m_old_values;
+        
         typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
 
         imp(ast_manager & m, params_ref const & p, stats & s) : 
@@ -208,6 +253,41 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(m_two);
         }        
 
+        double get_restart_armin(unsigned cnt_restarts)
+        {
+            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+            //printf("armin: %f\n", pow(1.1, inner_id + 1));
+            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
+        }
+
+        inline unsigned check_restart(unsigned curr_value)
+        {
+            if (curr_value > m_restart_limit)
+            {
+#if _RESTART_SCHEME_ == 4
+                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+#elif _RESTART_SCHEME_ == 3
+                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 2
+                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 1
+                if (m_stats.m_restarts & 1)
+                    m_restart_limit += _RESTART_LIMIT_;
+                else
+                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+#else
+                    m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
+                return 0;
+            }
+            return 1;
+        }
+
         ast_manager & m() const { return m_manager; }
 
         void set_cancel(bool f) { m_cancel = f; }
@@ -267,18 +347,18 @@ class sls_tactic : public tactic {
             #else
             double top_sum = 0.0;
             unsigned sz = g->size();
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
                 top_sum += m_tracker.get_score(e);
             }
 
-			TRACE("sls_top", tout << "Score distribution:"; 
+            TRACE("sls_top", tout << "Score distribution:"; 
                                     for (unsigned i = 0; i < sz; i++)
                                         tout << " " << m_tracker.get_score(g->form(i));
                                     tout << " AVG: " << top_sum / (double) sz << std::endl; );
 
 #if _CACHE_TOP_SCORE_
-			m_tracker.set_top_sum(top_sum);
+            m_tracker.set_top_sum(top_sum);
 #endif
 
             return top_sum / (double) sz;
@@ -292,20 +372,20 @@ class sls_tactic : public tactic {
         }
 
         double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.serious_update(fd, new_value);
+            m_evaluator.serious_update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
         }
 
         double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.update(fd, new_value);
+            m_evaluator.update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
@@ -314,18 +394,18 @@ class sls_tactic : public tactic {
 #if _EARLY_PRUNE_
         double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
             m_stats.m_incr_evals++;
-			if (m_evaluator.update_prune(fd, new_value))
+            if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-				return (m_tracker.get_top_sum() / g->size());
+                return (m_tracker.get_top_sum() / g->size());
 #else
-	            return top_score(g);
+                return top_score(g);
 #endif
-			else
-				return 0.0;
+            else
+                return 0.0;
         }
 #endif
 
-		// checks whether the score outcome of a given move is better than the previous score
+        // checks whether the score outcome of a given move is better than the previous score
         bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
 
@@ -357,11 +437,11 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// same as what_if, but only applied to the score of a specific atom, not the total score
+        // same as what_if, but only applied to the score of a specific atom, not the total score
         bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
             m_evaluator.update(fd, temp);
-			double r = m_tracker.get_score(e);
+            double r = m_tracker.get_score(e);
             if (r >= best_score) {
                 best_score = r;
                 best_const = fd_inx;            
@@ -378,29 +458,29 @@ class sls_tactic : public tactic {
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
 
-		}
+        }
 
-		// Andreas: do we really need all those temporary mpzs?
-		void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+        // Andreas: do we really need all those temporary mpzs?
+        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             mpz temp, mask, mask2;
             m_mpz_manager.mul(old_value, m_two, temp);
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
         }
 
         void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             m_mpz_manager.div(old_value, m_two, result);
         }
 
-		void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
             unsigned shift;        
             m_mpz_manager.add(old_value, m_one, incremented);
             if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
@@ -435,75 +515,77 @@ class sls_tactic : public tactic {
                 NOT_IMPLEMENTED_YET();
         }
 
-        void mk_random_move(goal_ref const & g) {
+        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
+        {
             unsigned rnd_mv = 0;
-			if (m_stats.m_moves > 10000)
-				rnd_mv = 0;
 
-			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
 
-			mpz new_value;
+            mpz new_value;
 
-			sort * srt = fd->get_range();
+            sort * srt = fd->get_range();
             if (m_manager.is_bool(srt))
-				m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-			else
-			{
+                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+            else
+            {
 #if _USE_ADDSUB_
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-				move_type mt = (move_type) rnd_mv;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+                move_type mt = (move_type) rnd_mv;
 
-				// inversion doesn't make sense, let's do a flip instead.
-				if (mt == MV_INV) mt = MV_FLIP;
+                // inversion doesn't make sense, let's do a flip instead.
+                if (mt == MV_INV) mt = MV_FLIP;
 #else
-				mt = MV_FLIP;
+                mt = MV_FLIP;
 #endif
-				unsigned bit = 0;
+                unsigned bit = 0;
 
-				switch (mt)
-				{
-					case MV_FLIP: {
-					unsigned bv_sz = m_bv_util.get_bv_size(srt);
-					bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-					mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-					break;
-				}
-				case MV_INC: 
-					mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_DEC: 
-					mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_INV:
-					mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				default:
-					NOT_IMPLEMENTED_YET();
-				}
+                switch (mt)
+                {
+                    case MV_FLIP: {
+                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
+                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+                    break;
+                }
+                case MV_INC: 
+                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_DEC: 
+                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_INV:
+                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                default:
+                    NOT_IMPLEMENTED_YET();
+                }
 
-				TRACE("sls", tout << "Randomization candidates: ";
-							 for (unsigned i = 0; i < unsat_constants.size(); i++)
-								 tout << unsat_constants[i]->get_name() << ", ";
-							 tout << std::endl;
-							 tout << "Random move: ";
-							 switch (mt) {
-							 case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-							 case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-							 case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-							 case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-							 }
-							 tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-			}
+                TRACE("sls", tout << "Randomization candidates: ";
+                             for (unsigned i = 0; i < unsat_constants.size(); i++)
+                                 tout << unsat_constants[i]->get_name() << ", ";
+                             tout << std::endl;
+                             tout << "Random move: ";
+                             switch (mt) {
+                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+                             }
+                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+            }
 
-			m_evaluator.update(fd, new_value);            
-			m_mpz_manager.del(new_value);
-		}
+            m_evaluator.update(fd, new_value);            
+            m_mpz_manager.del(new_value);
+        }
 
-		// will use VNS to ignore some possible moves and increase the flips per second
+        void mk_random_move(goal_ref const & g) {
+            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
+        }
+
+        // will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -514,7 +596,7 @@ class sls_tactic : public tactic {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
                 bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-				if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -536,12 +618,12 @@ class sls_tactic : public tactic {
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                         move = MV_INV;
 
-					// try to flip lsb
-					mk_flip(srt, old_value, 0, temp);                
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = 0;
-	                    move = MV_FLIP;
-					}
+                    // try to flip lsb
+                    mk_flip(srt, old_value, 0, temp);                
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = 0;
+                        move = MV_FLIP;
+                    }
                 }
 
                 // reset to what it was before
@@ -549,12 +631,12 @@ class sls_tactic : public tactic {
                 SASSERT(check == score);
             }
 
-			// we can either check the condition once in the beginning or check it repeatedly after every bit
+            // we can either check the condition once in the beginning or check it repeatedly after every bit
 #if _VNS_ == 1
-			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
 #else
-			if (new_score <= score)
-			for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+            if (new_score <= score)
+            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
 #endif
             for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
                 func_decl * fd = to_evaluate[i];
@@ -563,30 +645,30 @@ class sls_tactic : public tactic {
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 // What would happen if we flipped bit #j ?                
-				if (j < bv_sz)
-				{
-					mk_flip(srt, old_value, j, temp);                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);                
 
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = j;
-	                    move = MV_FLIP;
-	                }
-				}
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
                 SASSERT(check == score);
             }
-			m_mpz_manager.del(old_value);
+            m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
             return new_score;
         }        
 
-		// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
-			mpz temp2;
+            mpz temp2;
 #endif
             unsigned bv_sz;
             double new_score = score;
@@ -599,11 +681,11 @@ class sls_tactic : public tactic {
 
                 // first try to flip every bit
 #if _SKIP_BITS_
-				for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
 #else
-				for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
 #endif
-					// What would happen if we flipped bit #i ?                
+                    // What would happen if we flipped bit #i ?                
                     mk_flip(srt, old_value, j, temp);                
 
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
@@ -614,7 +696,7 @@ class sls_tactic : public tactic {
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
 #if _USE_ADDSUB_
-					if (!m_mpz_manager.is_even(old_value)) { 
+                    if (!m_mpz_manager.is_even(old_value)) { 
                         // for odd values, try +1
                         mk_inc(bv_sz, old_value, temp);
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
@@ -660,7 +742,7 @@ class sls_tactic : public tactic {
 
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
-				// Andreas: does not hold anymore now that we use top level score caching
+                // Andreas: does not hold anymore now that we use top level score caching
                 //SASSERT(check == score);
             }
 
@@ -669,17 +751,17 @@ class sls_tactic : public tactic {
 #if _USE_MUL3_
             m_mpz_manager.del(temp2);
 #endif
-			return new_score;
+            return new_score;
         }        
 
-		// same as find_best_move but only considers the score of the current expression instead of the overall score
-		double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+        // same as find_best_move but only considers the score of the current expression instead of the overall score
+        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
             unsigned bv_sz;
-			double new_score = m_tracker.get_score(e);
-			// Andreas: tie breaking not implemented yet
-			// double tie_score = top_score(g);
+            double new_score = m_tracker.get_score(e);
+            // Andreas: tie breaking not implemented yet
+            // double tie_score = top_score(g);
             for (unsigned i = 0; i < to_evaluate.size(); i++) {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
@@ -718,7 +800,7 @@ class sls_tactic : public tactic {
                 }
 
                 // reset to what it was before
-	            m_evaluator.update(fd, old_value);
+                m_evaluator.update(fd, old_value);
             }
 
             m_mpz_manager.del(old_value);
@@ -726,37 +808,37 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
-		// first try of intensification ... does not seem to be efficient
-		bool handle_plateau(goal_ref const & g)
-		{
-			unsigned sz = g->size();
+        // first try of intensification ... does not seem to be efficient
+        bool handle_plateau(goal_ref const & g)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned pos = m_stats.m_moves % sz;
+            unsigned pos = m_stats.m_moves % sz;
 #else
-			unsigned pos = m_tracker.get_random_uint(16) % sz;
+            unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-			{
-				m_tracker.get_value(to_evaluate[i]);
-				m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-			}            
-			unsigned new_const = (unsigned)-1, new_bit = 0;        
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+            {
+                m_tracker.get_value(to_evaluate[i]);
+                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+            }            
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
             mpz new_value;
             move_type move;
-			for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-			{
-				// Andreas: Could be extended to use (best) score but this is computationally more expensive.
+            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+            {
+                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
                 find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
 
                 if (new_const == static_cast<unsigned>(-1)) {
-					// Andreas: Actually this should never happen.
-					NOT_IMPLEMENTED_YET();
+                    // Andreas: Actually this should never happen.
+                    NOT_IMPLEMENTED_YET();
                 } else {
                     m_stats.m_moves++;
                     func_decl * fd = to_evaluate[new_const];
@@ -767,35 +849,35 @@ class sls_tactic : public tactic {
                     case MV_DEC: m_stats.m_decs++; break;
                     case MV_INV: m_stats.m_invs++; break;
                     case MV_UMIN: m_stats.m_umins++; break;
-					case MV_MUL2: m_stats.m_mul2s++; break;
-					case MV_MUL3: m_stats.m_mul3s++; break;
-					case MV_DIV2: m_stats.m_div2s++; break;
+                    case MV_MUL2: m_stats.m_mul2s++; break;
+                    case MV_MUL3: m_stats.m_mul3s++; break;
+                    case MV_DIV2: m_stats.m_div2s++; break;
                     }
                     
-					m_evaluator.update(fd, new_value);
+                    m_evaluator.update(fd, new_value);
                 }
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-				m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
 
-			m_old_values.reset();
+            m_old_values.reset();
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// what_if version needed in the context of 2nd intensification try, combining local and global score
+        // what_if version needed in the context of 2nd intensification try, combining local and global score
         bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
                         double & best_score, mpz & best_value, unsigned i) {
         
             double global_score = incremental_score(g, fd, temp);
-			double local_score = m_tracker.get_score(e);
+            double local_score = m_tracker.get_score(e);
             double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
-			if (new_score >= best_score) {
+            if (new_score >= best_score) {
                 best_score = new_score;
                 m_mpz_manager.set(best_value, temp);
                 return true;
@@ -804,17 +886,17 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// find_best_move version needed in the context of 2nd intensification try
+        // find_best_move version needed in the context of 2nd intensification try
         double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-		{
-			mpz old_value, temp;
+        {
+            mpz old_value, temp;
             double best_score = 0;
 
             sort * srt = fd->get_range();
             unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
             m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
-			for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
                 mk_flip(srt, old_value, j, temp);                
                 what_if(g, e, fd, temp, best_score, best_value, i); 
             }
@@ -822,54 +904,178 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
 
-			return best_score;
+            return best_score;
         }        
 
-		// second try to use intensification ... also not very effective
-		bool handle_plateau(goal_ref const & g, double old_score)
-		{
-			unsigned sz = g->size();
+        // second try to use intensification ... also not very effective
+        bool handle_plateau(goal_ref const & g, double old_score)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned new_const = m_stats.m_moves % sz;
+            unsigned new_const = m_stats.m_moves % sz;
 #else
-			unsigned new_const = m_tracker.get_random_uint(16) % sz;
+            unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
 
-			new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-			func_decl * fd = to_evaluate[new_const];
+            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+            func_decl * fd = to_evaluate[new_const];
 
-			mpz new_value;
-			//m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-			unsigned new_bit = 0;        
-			double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-			
-			for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-			{
+            mpz new_value;
+            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+            unsigned new_bit = 0;        
+            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+            
+            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+            {
                 new_score = find_best_move_local(g, q, fd, new_value, i);
 
                 m_stats.m_moves++;
                 m_stats.m_flips++;
 
-				global_score = incremental_score(g, fd, new_value);
-     			local_score = m_tracker.get_score(q);
+                global_score = incremental_score(g, fd, new_value);
+                local_score = m_tracker.get_score(q);
 
-				SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// main search loop
-		lbool search(goal_ref const & g) {        
+        // main search loop
+        lbool search(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            unsigned plateau_cnt = 0;
+
+            score = rescore(g);
+            unsigned sz = g->size();
+#if _PERC_STICKY_
+            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+
+#if _RESTARTS_ == 1
+            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 2
+            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 3
+            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
+                checkpoint();
+                m_stats.m_moves++;
+
+#if _REAL_RS_ || _REAL_PBFS_
+                //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
+
+#if _FOCUS_
+#if _PERC_STICKY_
+                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#else
+                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+                if (!e)
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+                if (!to_evaluate.size())
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+#endif
+
+#if _TYPE_RSTEP_
+                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                {
+#if _TYPE_RSTEP_ == 1
+                    m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
+                    mk_random_move(to_evaluate);
+#endif
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                }
+                continue;
+#endif
+
+#if _WEIGHT_DIST_ == 4
+                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
+                old_score = score;
+                new_const = (unsigned)-1;
+
+#if _VNS_
+                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+
+                if (new_const == static_cast<unsigned>(-1)) {
+                    score = old_score;
+                    plateau_cnt++;
+#if _INTENSIFICATION_
+                    handle_plateau(g, score);
+                    //handle_plateau(g);
+                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                        mk_random_move(to_evaluate);
+                    else
+#endif
+#if _REPICK_
+                    m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
+                    m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
+
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                } else {
+                    func_decl * fd = to_evaluate[new_const];              
+#if _REAL_RS_ || _REAL_PBFS_
+                    score = serious_score(g, fd, new_value);
+#else
+                    score = incremental_score(g, fd, new_value);    
+#endif
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        // main search loop
+        lbool search_old(goal_ref const & g) {        
             lbool res = l_undef;
             double score = 0.0, old_score = 0.0;
             unsigned new_const = (unsigned)-1, new_bit = 0;        
@@ -885,52 +1091,52 @@ class sls_tactic : public tactic {
         
             unsigned plateau_cnt = 0;
 
-			// Andreas: Why do we only allow so few plateaus?
+            // Andreas: Why do we only allow so few plateaus?
 #if _RESTARTS_
-			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
-					if (m_stats.m_moves == 5590)
                     checkpoint();
 
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
 #endif
             
 #if _TYPE_RSTEP_
-					if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-					{
+                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                    {
 #if _TYPE_RSTEP_ == 1
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #elif _TYPE_RSTEP_ == 2
-						mk_random_move(g);
+                        mk_random_move(g);
 #endif
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
-							} else
-								TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-						}
-					}
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                            } else
+                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                        }
+                    }
 #endif
                     old_score = score;
                     new_const = (unsigned)-1;
                         
-					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-					if (!to_evaluate.size())
-					{
-						res = l_true;
-						goto bailout;
-					}
+                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+                    if (!to_evaluate.size())
+                    {
+                        res = l_true;
+                        goto bailout;
+                    }
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
@@ -952,11 +1158,11 @@ class sls_tactic : public tactic {
                                         for (unsigned i = 0; i < g->size(); i++)
                                             tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
                                             m_tracker.get_score(g->form(i)) << std::endl; );
-						// Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                         score = old_score;
                     }
                     else {
-						// Andreas: Why does randomizing not count as a move? (Now it does.)
+                        // Andreas: Why does randomizing not count as a move? (Now it does.)
                         m_stats.m_moves++;
                         func_decl * fd = to_evaluate[new_const];
 
@@ -984,15 +1190,15 @@ class sls_tactic : public tactic {
                         case MV_DEC: m_stats.m_decs++; break;
                         case MV_INV: m_stats.m_invs++; break;
                         case MV_UMIN: m_stats.m_umins++; break;
-						case MV_MUL2: m_stats.m_mul2s++; break;
-						case MV_MUL3: m_stats.m_mul3s++; break;
-						case MV_DIV2: m_stats.m_div2s++; break;
+                        case MV_MUL2: m_stats.m_mul2s++; break;
+                        case MV_MUL3: m_stats.m_mul3s++; break;
+                        case MV_DIV2: m_stats.m_div2s++; break;
                         }
                     
 #if _REAL_RS_ || _REAL_PBFS_
-						score = serious_score(g, fd, new_value);
+                        score = serious_score(g, fd, new_value);
 #else
-						score = incremental_score(g, fd, new_value);    
+                        score = incremental_score(g, fd, new_value);    
 #endif
 
                         TRACE("sls", tout << "Score distribution:"; 
@@ -1004,7 +1210,7 @@ class sls_tactic : public tactic {
                     if (score >= 0.99999) {
 //                    if (score >= 1.0) {
                         // score could theoretically be imprecise.
-						// Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -1015,43 +1221,43 @@ class sls_tactic : public tactic {
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
-					/*
-					if (m_stats.m_moves % 100 == 0)
-					{
-						verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-						verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-					}*/
+                    /*
+                    if (m_stats.m_moves % 100 == 0)
+                    {
+                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+                    }*/
                 }
                 while (score > old_score && res == l_undef);                
-				
-				// Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                
+                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
                 if (score != old_score) {
-					report_tactic_progress("This should not happen I guess.", plateau_cnt);
+                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
                     plateau_cnt = 0;
-				} else {
-					m_stats.m_moves++;
+                } else {
+                    m_stats.m_moves++;
                     plateau_cnt++;
-					//report_tactic_progress("Plateau.", plateau_cnt);
-					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //report_tactic_progress("Plateau.", plateau_cnt);
+                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
                     //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
 #if _INTENSIFICATION_
-						handle_plateau(g, score);
-						//handle_plateau(g);
+                        handle_plateau(g, score);
+                        //handle_plateau(g);
 #else
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #endif
-						//mk_random_move(g);
+                        //mk_random_move(g);
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
@@ -1070,57 +1276,82 @@ class sls_tactic : public tactic {
                 return;
             }
 
-			verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-			verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-			verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-			verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-			verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-			verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-			verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-			verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-			verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-			verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-			verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-			verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-			verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-			verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-			verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-			verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-			verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-			verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-			verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-			verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-			verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-			verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-			verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-			
+            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
+            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
+            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
+            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+            
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
 #endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
+            m_restart_limit = _RESTART_LIMIT_;
+
             do {
                 checkpoint();
-				// Andreas: I think restarts are too impotant to ignore 99% of them are happening...
-                //if ((m_stats.m_restarts % 100) == 0)                        
-                    report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                
+
+                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 res = search(g);
 
                 if (res == l_undef)
-                    m_tracker.randomize();
+                {
+#if _RESTART_INIT_
+                    m_tracker.randomize(g);
+#else
+                    m_tracker.reset(g);
+#endif
+                }
             }
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
-			verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
 
             if (res == l_true) {    
-				report_tactic_progress("Number of flips:", m_stats.m_moves);
+                report_tactic_progress("Number of flips:", m_stats.m_moves);
+                for (unsigned i = 0; i < g->size(); i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                    {
+                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                        NOT_IMPLEMENTED_YET(); 
+                    }
+
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -1251,6 +1482,9 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
     // conservative gaussian elimination. 
     gaussian_p.set_uint("gaussian_max_occs", 2); 
 
+    params_ref ctx_p;
+    ctx_p.set_uint("max_depth", 32);
+    ctx_p.set_uint("max_steps", 5000000);
     return and_then(and_then(mk_simplify_tactic(m),                             
                              mk_propagate_values_tactic(m),
                              using_params(mk_solve_eqs_tactic(m), gaussian_p),
@@ -1259,7 +1493,11 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
+                        // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
+                        //mk_ctx_simplify_tactic(m, ctx_p),
+                        // Andreas: This one at least eliminates top level duplicates ...
+                        mk_simplify_tactic(m),
+                        // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index b26912e5c..0aca1f59c 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -29,31 +29,31 @@ class sls_tracker {
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
     mpz                   m_zero, m_one, m_two;
-	    
+        
     struct value_score { 
 #if _EARLY_PRUNE_
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
 #else
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
 #endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
 #if _EARLY_PRUNE_
-		double score_prune;
-		unsigned has_pos_occ;
-		unsigned has_neg_occ;
+        double score_prune;
+        unsigned has_pos_occ;
+        unsigned has_neg_occ;
 #endif
         unsigned distance; // max distance from any root
-		unsigned touched;
+        unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
-			touched = other.touched;
+            touched = other.touched;
             return *this;
         }
     };
@@ -65,6 +65,7 @@ private:
     typedef obj_map<expr, value_score> scores_type;    
     typedef obj_map<expr, ptr_vector<expr> > uplinks_type;    
     typedef obj_map<expr, ptr_vector<func_decl> > occ_type;
+    obj_hashtable<expr>	  m_top_expr;
     scores_type           m_scores;
     uplinks_type          m_uplinks;
     entry_point_type      m_entry_points;
@@ -72,18 +73,18 @@ private:
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
 #if _UCT_
-	unsigned              m_touched;
+    unsigned              m_touched;
 #endif
 #if _REAL_RS_ || _REAL_PBFS_
-	ptr_vector<expr>	  m_unsat_expr;
-	obj_map<expr, unsigned>	m_where_false;
-	expr**					m_list_false;
+    ptr_vector<expr>	  m_unsat_expr;
+    obj_map<expr, unsigned>	m_where_false;
+    expr**					m_list_false;
 #endif
 #if _CACHE_TOP_SCORE_
-	double				  m_top_sum;
+    double				  m_top_sum;
 #endif
-#if _WEIGHT_DIST_ == 4
-	double				  m_weight_dist_factor;
+#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
+    double				  m_weight_dist_factor;
 #endif
 
 public:    
@@ -104,24 +105,24 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
-#if _WEIGHT_DIST_ == 4
-	inline void set_weight_dist_factor(double val) {
-		m_weight_dist_factor = val;
-	}
+#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
+    inline void set_weight_dist_factor(double val) {
+        m_weight_dist_factor = val;
+    }
 #endif
 
 #if _CACHE_TOP_SCORE_
-	inline void adapt_top_sum(double add, double sub) {
-		m_top_sum += add - sub;
-	}
+    inline void adapt_top_sum(double add, double sub) {
+        m_top_sum += add - sub;
+    }
 
-	inline void set_top_sum(double new_score) {
-		m_top_sum = new_score;
-	}
+    inline void set_top_sum(double new_score) {
+        m_top_sum = new_score;
+    }
 
-	inline double get_top_sum() {
-		return m_top_sum;
-	}
+    inline double get_top_sum() {
+        return m_top_sum;
+    }
 #endif
 
     inline void set_value(expr * n, const mpz & r) {
@@ -174,20 +175,20 @@ public:
         m_scores.find(n).score_prune = score;
     }
 
-	inline double & get_score_prune(expr * n) {
+    inline double & get_score_prune(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).score_prune;
     }
 
-	inline unsigned has_pos_occ(expr * n) {
+    inline unsigned has_pos_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_pos_occ;
- 	}
+    }
 
-	inline unsigned has_neg_occ(expr * n) {
+    inline unsigned has_neg_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
- 	}
+    }
 #endif
 
     inline unsigned get_distance(expr * n) {
@@ -213,11 +214,62 @@ public:
         return m_uplinks.contains(n);
     }
 
+    inline bool is_top_expr(expr * n) {
+        return m_top_expr.contains(n);
+    }
+
     inline ptr_vector<expr> & get_uplinks(expr * n) {
         SASSERT(m_uplinks.contains(n));
         return m_uplinks.find(n);
     }
 
+#if _REAL_RS_ || _REAL_PBFS_
+    void debug_real(goal_ref const & g, unsigned flip)
+    {
+        unsigned count = 0;
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            expr * e = g->form(i);
+            if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e))
+            {
+                printf("iteration %d: ", flip);
+                printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size());
+                exit(4);
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e))
+            {
+                printf("iteration %d: ", flip);
+                printf("form %d is unsat but not in unsat list\n", i);
+                exit(4);
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e))
+            {
+                unsigned pos = m_where_false.find(e);
+                expr * q = m_list_false[pos];
+                if (q != e)
+                {
+                    printf("iteration %d: ", flip);
+                    printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos);
+                    exit(4);
+                }
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero))
+                count++;
+        }
+
+        // should be true now that duplicate assertions are removed
+        if (count != m_where_false.size())
+        {
+                printf("iteration %d: ", flip);
+                printf("%d are unsat but list is of size %d\n", count, m_where_false.size());
+                exit(4);
+        }
+    }
+#endif
+
     void initialize(app * n) {
         // Build score table
         if (!m_scores.contains(n)) {
@@ -316,45 +368,49 @@ public:
         }
     }
 
-	void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(proc, visited, q);
-			}
-		}
-		for_each_expr(proc, visited, e);
- 	}
+    void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(proc, visited, q);
+            }
+        }
+        for_each_expr(proc, visited, e);
+    }
 
-	void initialize_recursive(expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(q);
-			}
-		}
-		ptr_vector<func_decl> t;
+    void initialize_recursive(expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(q);
+            }
+        }
+        ptr_vector<func_decl> t;
         m_constants_occ.insert_if_not_there(e, t);
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
- 	}
+    }
 
-	void initialize(goal_ref const & g) {
+    void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            if (!m_top_expr.contains(e))
+                m_top_expr.insert(e);
+            else
+                printf("this is already in ...\n");
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2
-			initialize_recursive(proc, visited, e);
+            initialize_recursive(proc, visited, e);
 #endif
             for_each_expr(proc, visited, e);
         }
@@ -363,9 +419,9 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
-			initialize_recursive(e);
+            initialize_recursive(e);
 #endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
@@ -379,53 +435,61 @@ public:
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
 #if _REAL_RS_ || _REAL_PBFS_
-		m_list_false = new expr*[sz];
-        for (unsigned i = 0; i < sz; i++)
-	  		if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-				break_assertion(g->form(i));
+        m_list_false = new expr*[sz];
+        //for (unsigned i = 0; i < sz; i++)
+        //{
+        //	if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+        //		break_assertion(g->form(i));
+        //}
 #endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-	  		setup_occs(g->form(i));
+            setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-		m_touched = 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
 #endif
     }
 
 #if _REAL_RS_ || _REAL_PBFS_
-	void make_assertion(expr * e)
-	{
-		if (m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.find(e);
-			m_where_false.erase(e);
-			if (pos != m_where_false.size())
-			{
-				expr * q = m_list_false[m_where_false.size()];
-				m_list_false[pos] = q;
-				m_where_false.find(q) = pos;
-			}
+    void make_assertion(expr * e)
+    {
+        if (m_where_false.contains(e))
+        {
+            unsigned pos = m_where_false.find(e);
+            m_where_false.erase(e);
+            if (pos != m_where_false.size())
+            {
+                expr * q = m_list_false[m_where_false.size()];
+                m_list_false[pos] = q;
+                m_where_false.find(q) = pos;
+                //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos);
+            }
+            //else
+                //printf("Erasing %d from %d to %d\n", e, pos);
+//			m_list_false[m_where_false.size()] = 0;
 //			printf("Going in %d\n", m_where_false.size());
-		}
-		//if (m_unsat_expr.contains(e))
-			//m_unsat_expr.erase(e);
-	}
+        }
+        //if (m_unsat_expr.contains(e))
+            //m_unsat_expr.erase(e);
+    }
 
-	void break_assertion(expr * e)
-	{
-		if (!m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.size();
-			m_list_false[pos] = e;
-			m_where_false.insert(e, pos);
-	//		printf("Going in %d\n", m_where_false.size());
-		}
-		//if (!m_unsat_expr.contains(e))
-			//m_unsat_expr.push_back(e);
-	}
+    void break_assertion(expr * e)
+    {
+        //printf("I'm broken... that's still fine.\n");
+        if (!m_where_false.contains(e))
+        {
+            //printf("This however is not so cool...\n");
+            unsigned pos = m_where_false.size();
+            m_list_false[pos] = e;
+            m_where_false.insert(e, pos);
+    //		printf("Going in %d\n", m_where_false.size());
+        }
+        //if (!m_unsat_expr.contains(e))
+            //m_unsat_expr.push_back(e);
+    }
 #endif
 
     void show_model(std::ostream & out) {
@@ -522,7 +586,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize() {
+    void randomize(goal_ref const & g) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -534,38 +598,60 @@ public:
         }
 
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
+
+#if _UCT_RESET_
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
+#endif
+    }              
+
+    void reset(goal_ref const & g) {
+        TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
+
+        for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
+            mpz temp = m_zero;
+            set_value(it->m_value, temp);
+            m_mpz_manager.del(temp);
+        }
+
+#if _UCT_RESET_
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
+#endif
     }              
 
 #if _EARLY_PRUNE_
-	void setup_occs(expr * n, bool negated = false) {
-		if (m_manager.is_bool(n))
-		{
-			if (m_manager.is_and(n) || m_manager.is_or(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            expr * const * args = a->get_args();
-	            for (unsigned i = 0; i < a->get_num_args(); i++)
-					setup_occs(args[i]);
-			}
-			else if (m_manager.is_not(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            SASSERT(a->get_num_args() == 1);
-	            expr * child = a->get_arg(0);
-	            if (m_manager.is_and(child) || m_manager.is_or(child))
-	                NOT_IMPLEMENTED_YET();
-				setup_occs(child, true);
-			}
-			else
-			{
-				if (negated)
-					m_scores.find(n).has_neg_occ = 1;
-				else
-					m_scores.find(n).has_pos_occ = 1;
-			}
-		}
+    void setup_occs(expr * n, bool negated = false) {
+        if (m_manager.is_bool(n))
+        {
+            if (m_manager.is_and(n) || m_manager.is_or(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                expr * const * args = a->get_args();
+                for (unsigned i = 0; i < a->get_num_args(); i++)
+                    setup_occs(args[i]);
+            }
+            else if (m_manager.is_not(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                SASSERT(a->get_num_args() == 1);
+                expr * child = a->get_arg(0);
+                if (m_manager.is_and(child) || m_manager.is_or(child))
+                    NOT_IMPLEMENTED_YET();
+                setup_occs(child, true);
+            }
+            else
+            {
+                if (negated)
+                    m_scores.find(n).has_neg_occ = 1;
+                else
+                    m_scores.find(n).has_pos_occ = 1;
+            }
+        }
         else
             NOT_IMPLEMENTED_YET();
     }
@@ -574,7 +660,7 @@ public:
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
-		double res = 0.0;
+        double res = 0.0;
             
         if (is_uninterp_const(n)) {
             const mpz & r = get_value(n);
@@ -587,16 +673,24 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it does not even occur.
+            // Andreas: Seems to have no effect. Probably it does not even occur.
 #if _SCORE_AND_AVG_
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
+#if _DIRTY_UP_
+                sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 sum += get_score(args[i]);
+#endif
             res = sum / (double) a->get_num_args();
 #else
-			double min = 1.0;
+            double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 if (cur < min) min = cur;
             }
             res = min;
@@ -606,18 +700,26 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it is still too similar to the original version.
+            // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
 #if _SCORE_OR_MUL_
-			double inv = 1.0;
+            double inv = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 inv *= (1.0 - get_score(args[i]));
             }
             res = 1.0 - inv;
 #else
-			double max = 0.0;
+            double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 if (cur > max) max = cur;
             }
             res = max;
@@ -639,7 +741,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-			
+            
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -701,7 +803,7 @@ public:
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
                     res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-					m_mpz_manager.del(diff);
+                    m_mpz_manager.del(diff);
                 }
             }
             else {
@@ -762,7 +864,7 @@ public:
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
-			m_mpz_manager.del(x);
+            m_mpz_manager.del(x);
             m_mpz_manager.del(y);                
         }
         else if (m_manager.is_not(n)) {                
@@ -772,7 +874,11 @@ public:
             expr * child = a->get_arg(0);
             if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
                 NOT_IMPLEMENTED_YET();
+#if _DIRTY_UP_
+            res = is_top_expr(child) ? 0.0 : score_bool(child, true);
+#else
             res = score_bool(child, true);
+#endif
         }
         else if (m_manager.is_distinct(n)) {
             app * a = to_app(n);
@@ -797,25 +903,29 @@ public:
         SASSERT(res >= 0.0 && res <= 1.0);
 
 #if _WEIGHT_DIST_
-		app * a = to_app(n);
-		family_id afid = a->get_family_id();
+        app * a = to_app(n);
+        family_id afid = a->get_family_id();
 
-		if (afid == m_bv_util.get_family_id())
+        if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
-		if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+#if _WEIGHT_TOGGLE_
+        if (res < 1.0) res *= m_weight_dist_factor;
+#else
+        if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+#endif
 #elif _WEIGHT_DIST_ == 2
-		res *= res;
+        res *= res;
 #elif _WEIGHT_DIST_ == 3
-		if (res < 1.0) res = 0.0;
+        if (res < 1.0) res = 0.0;
 #elif _WEIGHT_DIST_ == 4
-		if (res < 1.0) res *= m_weight_dist_factor;
+        if (res < 1.0) res *= m_weight_dist_factor;
 #endif
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-	
+    
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -861,34 +971,34 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-	expr * get_unsat_expression(expr * e) {
-		if (m_manager.is_bool(e)) {
-			if (m_manager.is_and(e) || m_manager.is_or(e)) {
-				app * a = to_app(e);
-				expr * const * args = a->get_args();
-			    // Andreas: might be used for guided branching
-				//for (unsigned i = 0; i < a->get_num_args(); i++) {
-					//double cur = get_score(args[i]);
-				//}
-				// Andreas: A random number is better here since reusing flip will cause patterns.
-				unsigned int sz = a->get_num_args();
-				unsigned int pos = get_random_uint(16) % sz;
-				for (unsigned int i = pos; i < sz; i++) {
-	                expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-				}
-				for (unsigned int i = 0; i < pos; i++) {
-					expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-	            }
-	        }
-		}
-		return e;
-	}
+    expr * get_unsat_expression(expr * e) {
+        if (m_manager.is_bool(e)) {
+            if (m_manager.is_and(e) || m_manager.is_or(e)) {
+                app * a = to_app(e);
+                expr * const * args = a->get_args();
+                // Andreas: might be used for guided branching
+                //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                    //double cur = get_score(args[i]);
+                //}
+                // Andreas: A random number is better here since reusing flip will cause patterns.
+                unsigned int sz = a->get_num_args();
+                unsigned int pos = get_random_uint(16) % sz;
+                for (unsigned int i = pos; i < sz; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+                for (unsigned int i = 0; i < pos; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+            }
+        }
+        return e;
+    }
 
-	ptr_vector<func_decl> & get_constants(expr * e) {
+    ptr_vector<func_decl> & get_constants(expr * e) {
         ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
         unsigned sz = this_decls.size();
         for (unsigned i = 0; i < sz; i++) {
@@ -897,9 +1007,13 @@ public:
                 m_temp_constants.push_back(fd);
         }
         return m_temp_constants;
-	}
+    }
+
+    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+        if (sz == 1)
+            return get_constants();
+        m_temp_constants.reset();
 
-	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
@@ -913,247 +1027,394 @@ public:
             }
         }
         return m_temp_constants;
-	}
+    }
 
-	expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
-			for (unsigned i = pos; i < sz; i++) {
+    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+            for (unsigned i = pos; i < sz; i++) {
                 expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
-			}
-			for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
+                    return q;
             }
-			return 0;
-	}
+            for (unsigned i = 0; i < pos; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+                    return q;
+            }
+            return 0;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-			expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(g, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
-			if (!q)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            if (!q)
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
-			if (!e)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
+            if (!e || m_temp_constants.size())
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz = this_decls.size();
             for (unsigned j = 0; j < sz; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & go_deeper(expr * e) {
-			if (m_manager.is_bool(e)) {
-				if (m_manager.is_and(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-				    // Andreas: might be used for guided branching
-					//for (unsigned i = 0; i < a->get_num_args(); i++) {
-						//double cur = get_score(args[i]);
-					//}
-					// Andreas: A random number is better here since reusing flip will cause patterns.
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-				else if (m_manager.is_or(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-			}
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & go_deeper(expr * e) {
+            if (m_manager.is_bool(e)) {
+                if (m_manager.is_and(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    // Andreas: might be used for guided branching
+                    //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                        //double cur = get_score(args[i]);
+                    //}
+                    // Andreas: A random number is better here since reusing flip will cause patterns.
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+                else if (m_manager.is_or(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+            }
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-		expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(g, sz, pos);
         if (!q)
-			return m_temp_constants;
+            return m_temp_constants;
 
-		return go_deeper(q);
-	}
+        return go_deeper(q);
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
-			if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
-				return m_temp_constants;
-			else
-	            return get_constants();
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+                return m_temp_constants;
+            else
+                return get_constants();
         }
         else {
             m_temp_constants.reset();
 #if _FOCUS_ == 1
 #if _UCT_
-			unsigned pos = -1;
-			value_score vscore;
+            unsigned pos = -1;
+            value_score vscore;
 #if _PROBABILISTIC_UCT_
-			double sum_score = 0.0;
-			unsigned start_index = get_random_uint(16) % sz;
-			for (unsigned i = start_index; i < sz; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
-			for (unsigned i = 0; i < start_index; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
+            double sum_score = 0.0;
+            unsigned start_index = get_random_uint(16) % sz;
+            
+            for (unsigned i = start_index; i < sz; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+                double q = vscore.score * vscore.score; 
 #else
-			double max = -1.0;
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
-#if _UCT_ == 1
-				double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-#elif _UCT_ == 2
-				double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
 #endif
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }	
+            }
+            for (unsigned i = 0; i < start_index; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+                double q = vscore.score * vscore.score; 
+#else
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }	
+            }
+#else
+            double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+//            for (unsigned i = 0; i < m_where_false.size(); i++) {
+//                expr * e = m_list_false[i];
+                vscore = m_scores.find(e);
+#if _UCT_ == 1
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#elif _UCT_ == 2
+                double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#endif
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
 #endif
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
 
 #if _UCT_ == 1
-			m_scores.find(g->form(pos)).touched++;
-			m_touched++;
+            m_scores.find(g->form(pos)).touched++;
+            m_touched++;
 #elif _UCT_ == 2
-			m_scores.find(g->form(pos)).touched = flip; 
+            m_scores.find(g->form(pos)).touched = flip; 
 #endif
-			expr * e = g->form(pos);
+            expr * e = g->form(pos);
+//            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
-			unsigned int pos = -1;
-			double max = -1.0;
+            unsigned int pos = -1;
+            double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 2
-			unsigned int pos = -1;
-			double min = 2.0;
+            unsigned int pos = -1;
+            double min = 2.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+                if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 1
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #elif _UNIFORM_RANDOM_
-			unsigned cnt_unsat = 0, pos = -1;
-			for (unsigned i = 0; i < sz; i++)
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            unsigned cnt_unsat = 0, pos = -1;
+            for (unsigned i = 0; i < sz; i++)
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _REAL_RS_
-			//unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[get_random_uint(16) % sz];
+            //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            expr * e = m_list_false[get_random_uint(16) % sz];
 #elif _REAL_PBFS_
-			//unsigned pos = m_false_list[flip % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[flip % sz];
+            //unsigned pos = m_false_list[flip % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            else
+                expr * e = m_list_false[flip % sz];
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #endif
-			return get_unsat_constants_walksat(e);
+            return get_unsat_constants_walksat(e);
 #elif _FOCUS_ == 2
 #if _BFS_
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
 #endif
-			return get_unsat_constants_crsat(g, sz, pos);
+            return get_unsat_constants_crsat(g, sz, pos);
 #else
-			return get_unsat_constants_gsat(g, sz);
+            return get_unsat_constants_gsat(g, sz);
 #endif
         }
     }
+    
+
+    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
+
+        if (sz == 1)
+            return g->form(0);
+
+        m_temp_constants.reset();
+#if _FOCUS_ == 1
+#if _UCT_
+        unsigned pos = -1;
+        value_score vscore;
+#if _PROBABILISTIC_UCT_
+        double sum_score = 0.0;
+        unsigned start_index = get_random_uint(16) % sz;
+            
+        for (unsigned i = start_index; i < sz; i++)
+        {
+            expr * e = g->form(i);
+            vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+            double q = vscore.score * vscore.score + _UCT_EPS_; 
+#else
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                sum_score += q;
+                if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                    pos = i;
+            }	
+        }
+        for (unsigned i = 0; i < start_index; i++)
+        {
+            expr * e = g->form(i);
+            vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+            double q = vscore.score * vscore.score + _UCT_EPS_; 
+#else
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                sum_score += q;
+                if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                    pos = i;
+            }	
+        }
+#else
+        double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+//            for (unsigned i = 0; i < m_where_false.size(); i++) {
+//                expr * e = m_list_false[i];
+                vscore = m_scores.find(e);
+#if _UCT_ == 1
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#elif _UCT_ == 2
+            double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#endif
+            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+            }
+#endif
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+
+#if _UCT_ == 1
+        m_scores.find(g->form(pos)).touched++;
+        m_touched++;
+#elif _UCT_ == 2
+        m_scores.find(g->form(pos)).touched = flip; 
+#endif
+//        return m_list_false[pos];
+        return g->form(pos);
+
+#elif _BFS_ == 3
+        unsigned int pos = -1;
+        double max = -1.0;
+        for (unsigned i = 0; i < sz; i++) {
+            expr * e = g->form(i);
+               double q = get_score(e);
+            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _BFS_ == 2
+        unsigned int pos = -1;
+        double min = 2.0;
+        for (unsigned i = 0; i < sz; i++) {
+            expr * e = g->form(i);
+               double q = get_score(e);
+            if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+        }
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _BFS_ == 1
+        unsigned int pos = flip % sz;
+        return get_unsat_assertion(g, sz, pos);
+#elif _UNIFORM_RANDOM_
+        unsigned cnt_unsat = 0, pos = -1;
+        for (unsigned i = 0; i < sz; i++)
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _REAL_RS_
+        //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+        //expr * e = get_unsat_assertion(g, sz, pos);
+        //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+        sz = m_where_false.size();
+        if (sz == 0)
+            return 0;
+        return m_list_false[get_random_uint(16) % sz];
+#elif _REAL_PBFS_
+        //unsigned pos = m_false_list[flip % m_cnt_false];
+        //expr * e = get_unsat_assertion(g, sz, pos);
+        //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+        sz = m_where_false.size();
+        if (sz == 0)
+            return0;
+        else
+            return m_list_false[flip % sz];
+#else
+        unsigned int pos = get_random_uint(16) % sz;
+        return get_unsat_assertion(g, sz, pos);
+#endif
+        return g->form(pos);
+#elif _FOCUS_ == 2
+#if _BFS_
+        unsigned int pos = flip % sz;
+#else
+        unsigned int pos = get_random_uint(16) % sz;
+#endif
+        return get_unsat_constants_crsat(g, sz, pos);
+#endif
+    }
 };
 
 #endif
\ No newline at end of file

From 3d6f8840c65071f186a4955665cbd4db16a53be6 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 17:04:38 +0000
Subject: [PATCH 006/108] SLS refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h |  158 +++
 src/tactic/sls/sls_engine.cpp             | 1160 +++++++++++++++++
 src/tactic/sls/sls_engine.h               |  159 +++
 src/tactic/sls/sls_evaluator.h            |    3 +
 src/tactic/sls/sls_tactic.cpp             | 1396 +--------------------
 src/tactic/sls/sls_tracker.h              |   10 +-
 6 files changed, 1520 insertions(+), 1366 deletions(-)
 create mode 100644 src/tactic/sls/sls_compilation_settings.h
 create mode 100644 src/tactic/sls/sls_engine.cpp
 create mode 100644 src/tactic/sls/sls_engine.h

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
new file mode 100644
index 000000000..aea4787b0
--- /dev/null
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -0,0 +1,158 @@
+/*++
+Copyright (c) 2014 Microsoft Corporation
+
+Module Name:
+
+    sls_compilation_constants.h
+
+Abstract:
+
+    Stochastic Local Search (SLS) compilation constants
+
+Author:
+
+    Christoph (cwinter) 2014-03-19
+
+Notes:
+
+    This file should go away completely once we have evaluated all options.
+
+--*/
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
+#define _FOCUS_ 1
+
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 0
+
+// do we use restarts?
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 3.0
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
+#define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
+#define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
+#define _VNS_ 0
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 1
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.25
+
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 1
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 10.0
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
+#define _PROBABILISTIC_UCT_ 0
+
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 1
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 0
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 0
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 0
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 0
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
+InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+InvalidConfiguration;
+#endif
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+InvalidConfiguration;
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
new file mode 100644
index 000000000..92471aad8
--- /dev/null
+++ b/src/tactic/sls/sls_engine.cpp
@@ -0,0 +1,1160 @@
+/*++
+Copyright (c) 2012 Microsoft Corporation
+
+Module Name:
+
+    sls_engine.cpp
+
+Abstract:
+
+    A Stochastic Local Search (SLS) engine
+
+Author:
+
+    Christoph (cwinter) 2014-03-19
+
+Notes:
+
+--*/
+#include<iomanip>
+
+#include"map.h"
+#include"ast_smt2_pp.h"
+#include"ast_pp.h"
+#include"var_subst.h"
+#include"model_pp.h"
+#include"tactic.h"
+#include"cooperate.h"
+#include"luby.h"
+
+#include"sls_compilation_settings.h"
+#include"sls_params.hpp"
+#include"sls_engine.h"
+
+
+sls_engine::sls_engine(ast_manager & m, params_ref const & p) :
+    m_manager(m),    
+    m_powers(m_mpz_manager),
+    m_zero(m_mpz_manager.mk_z(0)),
+    m_one(m_mpz_manager.mk_z(1)),
+    m_two(m_mpz_manager.mk_z(2)),
+    m_cancel(false),
+    m_bv_util(m),
+    m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
+    m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers)
+{
+    updt_params(p);
+}
+
+sls_engine::~sls_engine() {
+    m_mpz_manager.del(m_zero);
+    m_mpz_manager.del(m_one);
+    m_mpz_manager.del(m_two);
+}
+
+double sls_engine::get_restart_armin(unsigned cnt_restarts)
+{
+    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+    //printf("armin: %f\n", pow(1.1, inner_id + 1));
+    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
+}    
+
+void sls_engine::updt_params(params_ref const & _p) {
+    sls_params p(_p);
+    m_produce_models = _p.get_bool("model", false);
+    m_max_restarts = p.restarts();
+    m_tracker.set_random_seed(p.random_seed());
+    m_plateau_limit = p.plateau_limit();
+}
+
+void sls_engine::checkpoint() {
+    if (m_cancel)
+        throw tactic_exception(TACTIC_CANCELED_MSG);
+    cooperate("sls");
+}
+
+bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
+    bool res = true;
+
+    unsigned sz = g->size();
+    for (unsigned i = 0; i < sz && res; i++) {
+        checkpoint();
+        expr_ref o(m_manager);
+
+        if (!mdl.eval(g->form(i), o, true))
+            exit(ERR_INTERNAL_FATAL);
+
+        res = m_manager.is_true(o.get());
+    }
+
+    TRACE("sls", tout << "Evaluation: " << res << std::endl;);
+
+    return res;
+}
+
+double sls_engine::top_score(goal_ref const & g) {
+#if 0
+    double min = m_tracker.get_score(g->form(0));
+    unsigned sz = g->size();
+    for (unsigned i = 1; i < sz; i++) {
+        double q = m_tracker.get_score(g->form(i));
+        if (q < min) min = q;
+    }
+    TRACE("sls_top", tout << "Score distribution:";
+    for (unsigned i = 0; i < sz; i++)
+        tout << " " << m_tracker.get_score(g->form(i));
+    tout << " MIN: " << min << std::endl;);
+    return min;
+#else
+    double top_sum = 0.0;
+    unsigned sz = g->size();
+    for (unsigned i = 0; i < sz; i++) {
+        expr * e = g->form(i);
+        top_sum += m_tracker.get_score(e);
+    }
+
+    TRACE("sls_top", tout << "Score distribution:";
+    for (unsigned i = 0; i < sz; i++)
+        tout << " " << m_tracker.get_score(g->form(i));
+    tout << " AVG: " << top_sum / (double)sz << std::endl;);
+
+#if _CACHE_TOP_SCORE_
+    m_tracker.set_top_sum(top_sum);
+#endif
+
+    return top_sum / (double)sz;
+#endif
+}
+
+double sls_engine::rescore(goal_ref const & g) {
+    m_evaluator.update_all();
+    m_stats.m_full_evals++;
+    return top_score(g);
+}
+
+double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+    m_evaluator.serious_update(fd, new_value);
+    m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+    return (m_tracker.get_top_sum() / g->size());
+#else
+    return top_score(g);
+#endif
+}
+
+double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+    m_evaluator.update(fd, new_value);
+    m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+    return (m_tracker.get_top_sum() / g->size());
+#else
+    return top_score(g);
+#endif
+}
+
+double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+#if _EARLY_PRUNE_
+    m_stats.m_incr_evals++;
+    if (m_evaluator.update_prune(fd, new_value))
+#if _CACHE_TOP_SCORE_
+        return (m_tracker.get_top_sum() / g->size());
+#else
+        return top_score(g);
+#endif
+    else
+        return 0.0;
+#else
+    NOT_IMPLEMENTED_YET();
+#endif
+}
+
+// checks whether the score outcome of a given move is better than the previous score
+bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
+
+#ifdef Z3DEBUG
+    mpz old_value;
+    m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+#endif
+
+#if _EARLY_PRUNE_
+    double r = incremental_score_prune(g, fd, temp);
+#else
+    double r = incremental_score(g, fd, temp);
+#endif   
+#ifdef Z3DEBUG
+    TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
+            " --> " << r << std::endl;);
+
+    m_mpz_manager.del(old_value);
+#endif
+
+    //            if (r >= best_score) {
+    if (r > best_score) {
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
+// same as what_if, but only applied to the score of a specific atom, not the total score
+bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                    double & best_score, unsigned & best_const, mpz & best_value) {
+    m_evaluator.update(fd, temp);
+    double r = m_tracker.get_score(e);
+    if (r >= best_score) {
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
+void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
+    mpz temp, mask, mask2;
+    m_mpz_manager.add(old_value, add_value, temp);
+    m_mpz_manager.set(mask, m_powers(bv_sz));
+    m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+    m_mpz_manager.bitwise_and(temp, mask2, result);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(mask);
+    m_mpz_manager.del(mask2);
+
+}
+
+// Andreas: do we really need all those temporary mpzs?
+void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+    mpz temp, mask, mask2;
+    m_mpz_manager.mul(old_value, m_two, temp);
+    m_mpz_manager.set(mask, m_powers(bv_sz));
+    m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+    m_mpz_manager.bitwise_and(temp, mask2, result);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(mask);
+    m_mpz_manager.del(mask2);
+}
+
+void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+    m_mpz_manager.div(old_value, m_two, result);
+}
+
+void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+    unsigned shift;
+    m_mpz_manager.add(old_value, m_one, incremented);
+    if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
+        m_mpz_manager.set(incremented, m_zero);
+}
+
+void sls_engine::mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
+    if (m_mpz_manager.is_zero(old_value)) {
+        m_mpz_manager.set(decremented, m_powers(bv_sz));
+        m_mpz_manager.dec(decremented);
+    }
+    else
+        m_mpz_manager.sub(old_value, m_one, decremented);
+}
+
+void sls_engine::mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
+    m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
+}
+
+void sls_engine::mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
+    m_mpz_manager.set(flipped, m_zero);
+
+    if (m_bv_util.is_bv_sort(s)) {
+        mpz mask;
+        m_mpz_manager.set(mask, m_powers(bit));
+        m_mpz_manager.bitwise_xor(old_value, mask, flipped);
+        m_mpz_manager.del(mask);
+    }
+    else if (m_manager.is_bool(s))
+        m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
+    else
+        NOT_IMPLEMENTED_YET();
+}
+
+void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
+{
+    unsigned rnd_mv = 0;
+    unsigned ucc = unsat_constants.size();
+    unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
+    func_decl * fd = unsat_constants[rc];
+
+    mpz new_value;
+
+    sort * srt = fd->get_range();
+    if (m_manager.is_bool(srt))
+        m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+    else
+    {
+#if _USE_ADDSUB_
+        if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
+        if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+        move_type mt = (move_type)rnd_mv;
+
+        // inversion doesn't make sense, let's do a flip instead.
+        if (mt == MV_INV) mt = MV_FLIP;
+#else
+        mt = MV_FLIP;
+#endif
+        unsigned bit = 0;
+
+        switch (mt)
+        {
+        case MV_FLIP: {
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+            mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+            break;
+        }
+        case MV_INC:
+            mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+            break;
+        case MV_DEC:
+            mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+            break;
+        case MV_INV:
+            mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+            break;
+        default:
+            NOT_IMPLEMENTED_YET();
+        }
+
+        TRACE("sls", tout << "Randomization candidates: ";
+        for (unsigned i = 0; i < unsat_constants.size(); i++)
+            tout << unsat_constants[i]->get_name() << ", ";
+        tout << std::endl;
+        tout << "Random move: ";
+        switch (mt) {
+        case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+        case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+        case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+        case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+        }
+        tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout););
+    }
+
+    m_evaluator.update(fd, new_value);
+    m_mpz_manager.del(new_value);
+}
+
+void sls_engine::mk_random_move(goal_ref const & g) {
+    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
+}
+
+// will use VNS to ignore some possible moves and increase the flips per second
+double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+    unsigned bv_sz, max_bv_sz = 0;
+    double new_score = score;
+
+    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+            // try to flip lsb
+            mk_flip(srt, old_value, 0, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = 0;
+                move = MV_FLIP;
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        SASSERT(check == score);
+    }
+
+    // we can either check the condition once in the beginning or check it repeatedly after every bit
+#if _VNS_ == 1
+    for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+    if (new_score <= score)
+        for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
+// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+    mpz temp2;
+#endif
+    unsigned bv_sz;
+    double new_score = score;
+
+    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        // first try to flip every bit
+#if _SKIP_BITS_
+        for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
+#else
+        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+            // What would happen if we flipped bit #i ?                
+            mk_flip(srt, old_value, j, temp);
+
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = j;
+                move = MV_FLIP;
+            }
+        }
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+#if _USE_ADDSUB_
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+#endif
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+            mk_inc(bv_sz, temp, temp2);
+            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+            // try multiplication by 2
+            mk_mul2(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_MUL2;
+
+#if _USE_MUL3_
+            // try multiplication by 3
+            mk_add(bv_sz, old_value, temp, temp2);
+            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                move = MV_MUL3;
+#endif
+
+            // try division by 2
+            mk_div2(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_DIV2;
+#endif
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        // Andreas: does not hold anymore now that we use top level score caching
+        //SASSERT(check == score);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+#if _USE_MUL3_
+    m_mpz_manager.del(temp2);
+#endif
+    return new_score;
+}
+
+// same as find_best_move but only considers the score of the current expression instead of the overall score
+double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+    unsigned bv_sz;
+    double new_score = m_tracker.get_score(e);
+    // Andreas: tie breaking not implemented yet
+    // double tie_score = top_score(g);
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        // first try to flip every bit
+        for (unsigned j = 0; j < bv_sz; j++) {
+            // What would happen if we flipped bit #i ?                
+            mk_flip(srt, old_value, j, temp);
+
+            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = j;
+                move = MV_FLIP;
+            }
+        }
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+        }
+
+        // reset to what it was before
+        m_evaluator.update(fd, old_value);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
+// first try of intensification ... does not seem to be efficient
+bool sls_engine::handle_plateau(goal_ref const & g)
+{
+    unsigned sz = g->size();
+#if _BFS_
+    unsigned pos = m_stats.m_moves % sz;
+#else
+    unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+    if (!e)
+        return 0;
+
+    expr * q = m_tracker.get_unsat_expression(e);
+    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+    for (unsigned i = 0; i < to_evaluate.size(); i++)
+    {
+        m_tracker.get_value(to_evaluate[i]);
+        m_old_values.push_back(&m_tracker.get_value(to_evaluate[i]));
+    }
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+    for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+    {
+        // Andreas: Could be extended to use (best) score but this is computationally more expensive.
+        find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
+
+        if (new_const == static_cast<unsigned>(-1)) {
+            // Andreas: Actually this should never happen.
+            NOT_IMPLEMENTED_YET();
+        }
+        else {
+            m_stats.m_moves++;
+            func_decl * fd = to_evaluate[new_const];
+
+            switch (move) {
+            case MV_FLIP: m_stats.m_flips++; break;
+            case MV_INC: m_stats.m_incs++; break;
+            case MV_DEC: m_stats.m_decs++; break;
+            case MV_INV: m_stats.m_invs++; break;
+            case MV_UMIN: m_stats.m_umins++; break;
+            case MV_MUL2: m_stats.m_mul2s++; break;
+            case MV_MUL3: m_stats.m_mul3s++; break;
+            case MV_DIV2: m_stats.m_div2s++; break;
+            }
+
+            m_evaluator.update(fd, new_value);
+        }
+
+        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+            return 1;
+    }
+
+    for (unsigned i = 0; i < to_evaluate.size(); i++)
+        m_tracker.set_value(to_evaluate[i], *m_old_values[i]);
+
+    m_old_values.reset();
+
+    return 0;
+}
+
+// what_if version needed in the context of 2nd intensification try, combining local and global score
+bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                double & best_score, mpz & best_value, unsigned i) {
+
+    double global_score = incremental_score(g, fd, temp);
+    double local_score = m_tracker.get_score(e);
+    double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+    if (new_score >= best_score) {
+        best_score = new_score;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
+// find_best_move version needed in the context of 2nd intensification try
+double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+{
+    mpz old_value, temp;
+    double best_score = 0;
+
+    sort * srt = fd->get_range();
+    unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+    m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+    for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+        mk_flip(srt, old_value, j, temp);
+        what_if(g, e, fd, temp, best_score, best_value, i);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+
+    return best_score;
+}
+
+// second try to use intensification ... also not very effective
+bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
+{
+    unsigned sz = g->size();
+#if _BFS_
+    unsigned new_const = m_stats.m_moves % sz;
+#else
+    unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+    if (!e)
+        return 0;
+
+    expr * q = m_tracker.get_unsat_expression(e);
+    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+    new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+    func_decl * fd = to_evaluate[new_const];
+
+    mpz new_value;
+    //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+    unsigned new_bit = 0;
+    double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+
+    for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+    {
+        new_score = find_best_move_local(g, q, fd, new_value, i);
+
+        m_stats.m_moves++;
+        m_stats.m_flips++;
+
+        global_score = incremental_score(g, fd, new_value);
+        local_score = m_tracker.get_score(q);
+
+        SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+            return 1;
+    }
+
+    return 0;
+}
+
+// main search loop
+lbool sls_engine::search(goal_ref const & g) {
+    lbool res = l_undef;
+    double score = 0.0, old_score = 0.0;
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+    unsigned plateau_cnt = 0;
+
+    score = rescore(g);
+    unsigned sz = g->size();
+#if _PERC_STICKY_
+    expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#endif
+
+#if _RESTARTS_ == 1
+    while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#elif _RESTARTS_ == 2
+    while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#elif _RESTARTS_ == 3
+    while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#else
+    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#endif
+        checkpoint();
+        m_stats.m_moves++;
+
+#if _REAL_RS_ || _REAL_PBFS_
+        //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
+
+#if _FOCUS_
+#if _PERC_STICKY_
+        if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+            e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#else
+        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#endif
+        if (!e)
+        {
+            res = l_true;
+            goto bailout;
+        }
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+        if (!to_evaluate.size())
+        {
+            res = l_true;
+            goto bailout;
+        }
+#endif
+
+#if _TYPE_RSTEP_
+        if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+        {
+#if _TYPE_RSTEP_ == 1
+            m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
+            mk_random_move(to_evaluate);
+#endif
+#if _CACHE_TOP_SCORE_
+            score = m_tracker.get_top_sum() / g->size();
+#else
+            score = top_score(g);
+#endif
+        }
+        continue;
+#endif
+
+#if _WEIGHT_DIST_ == 4
+        m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
+        old_score = score;
+        new_const = (unsigned)-1;
+
+#if _VNS_
+        score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+
+        if (new_const == static_cast<unsigned>(-1)) {
+            score = old_score;
+            plateau_cnt++;
+#if _INTENSIFICATION_
+            handle_plateau(g, score);
+            //handle_plateau(g);
+            //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+            //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+            if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                mk_random_move(to_evaluate);
+            else
+#endif
+#if _REPICK_
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
+                m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
+
+#if _CACHE_TOP_SCORE_
+            score = m_tracker.get_top_sum() / g->size();
+#else
+            score = top_score(g);
+#endif
+        }
+        else {
+            func_decl * fd = to_evaluate[new_const];
+#if _REAL_RS_ || _REAL_PBFS_
+            score = serious_score(g, fd, new_value);
+#else
+            score = incremental_score(g, fd, new_value);
+#endif
+        }
+    }
+
+bailout:
+    m_mpz_manager.del(new_value);
+
+    return res;
+}
+
+// main search loop
+lbool sls_engine::search_old(goal_ref const & g) {
+    lbool res = l_undef;
+    double score = 0.0, old_score = 0.0;
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+
+    score = rescore(g);
+    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+    tout << "Score distribution:";
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    tout << " TOP: " << score << std::endl;);
+
+    unsigned plateau_cnt = 0;
+
+    // Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+    while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+        //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {
+#endif
+        do {
+            checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+
+#if _TYPE_RSTEP_
+            if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+            {
+#if _TYPE_RSTEP_ == 1
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+                mk_random_move(g);
+#endif
+                score = top_score(g);
+
+                if (score >= 1.0) {
+                    bool all_true = true;
+                    for (unsigned i = 0; i < g->size() && all_true; i++)
+                        if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                            all_true = false;
+                    if (all_true) {
+                        res = l_true; // sat
+                        goto bailout;
+                    }
+                    else
+                        TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                }
+            }
+#endif
+            old_score = score;
+            new_const = (unsigned)-1;
+
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+            if (!to_evaluate.size())
+            {
+                res = l_true;
+                goto bailout;
+            }
+            TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                tout << to_evaluate[i]->get_name() << std::endl;);
+
+#if _VNS_
+            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+            if (new_const == static_cast<unsigned>(-1)) {
+                TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
+                for (unsigned i = 0; i < g->size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                });
+
+                TRACE("sls_max", m_tracker.show_model(tout);
+                tout << "Scores: " << std::endl;
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
+                    m_tracker.get_score(g->form(i)) << std::endl;);
+                // Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                score = old_score;
+            }
+            else {
+                // Andreas: Why does randomizing not count as a move? (Now it does.)
+                m_stats.m_moves++;
+                func_decl * fd = to_evaluate[new_const];
+
+                TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
+                switch (move) {
+                case MV_FLIP:
+                    tout << "Flip";
+                    if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
+                    break;
+                case MV_INC:
+                    tout << "+1";
+                    break;
+                case MV_DEC:
+                    tout << "-1";
+                    break;
+                case MV_INV:
+                    tout << "NEG";
+                    break;
+                };
+                tout << ") ; new score = " << std::setprecision(32) << score << std::endl;);
+
+                switch (move) {
+                case MV_FLIP: m_stats.m_flips++; break;
+                case MV_INC: m_stats.m_incs++; break;
+                case MV_DEC: m_stats.m_decs++; break;
+                case MV_INV: m_stats.m_invs++; break;
+                case MV_UMIN: m_stats.m_umins++; break;
+                case MV_MUL2: m_stats.m_mul2s++; break;
+                case MV_MUL3: m_stats.m_mul3s++; break;
+                case MV_DIV2: m_stats.m_div2s++; break;
+                }
+
+#if _REAL_RS_ || _REAL_PBFS_
+                score = serious_score(g, fd, new_value);
+#else
+                score = incremental_score(g, fd, new_value);
+#endif
+
+                TRACE("sls", tout << "Score distribution:";
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                tout << " TOP: " << score << std::endl;);
+            }
+
+            if (score >= 0.99999) {
+                //                    if (score >= 1.0) {
+                // score could theoretically be imprecise.
+                // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                bool all_true = true;
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        all_true = false;
+                if (all_true) {
+                    res = l_true; // sat
+                    goto bailout;
+                }
+                else
+                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+            }
+            /*
+            if (m_stats.m_moves % 100 == 0)
+            {
+            verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+            verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+            }*/
+        } while (score > old_score && res == l_undef);
+
+        // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+        if (score != old_score) {
+            report_tactic_progress("This should not happen I guess.", plateau_cnt);
+            plateau_cnt = 0;
+        }
+        else {
+            m_stats.m_moves++;
+            plateau_cnt++;
+            //report_tactic_progress("Plateau.", plateau_cnt);
+            // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+            //if (plateau_cnt < m_plateau_limit) {
+            TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
+#if _INTENSIFICATION_
+            handle_plateau(g, score);
+            //handle_plateau(g);
+#else
+            m_evaluator.randomize_local(g, m_stats.m_moves);
+#endif
+            //mk_random_move(g);
+            score = top_score(g);
+
+            if (score >= 1.0) {
+                bool all_true = true;
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        all_true = false;
+                if (all_true) {
+                    res = l_true; // sat
+                    goto bailout;
+                }
+                else
+                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+            }
+        }
+    }
+
+bailout:
+    m_mpz_manager.del(new_value);
+
+    return res;
+}
+
+void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
+    if (g->inconsistent()) {
+        mc = 0;
+        return;
+    }
+
+    m_produce_models = g->models_enabled();
+
+    verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+    verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+    verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
+    verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+    verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+    verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+    verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
+    verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+    verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+    verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+    verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+    verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+    verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+    verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+    verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+    verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+    verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
+    verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+    verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+    verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+    verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+    verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+    verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+    verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+    verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+    verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+    verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+    verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+    verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+    verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+    verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+    verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+    verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+    verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+    verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(g);
+    lbool res = l_undef;
+
+    m_restart_limit = _RESTART_LIMIT_;
+
+    do {
+        checkpoint();
+
+        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+        res = search(g);
+
+        if (res == l_undef)
+        {
+#if _RESTART_INIT_
+            m_tracker.randomize(g);
+#else
+            m_tracker.reset(g);
+#endif
+        }
+    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+
+    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+
+    if (res == l_true) {
+        report_tactic_progress("Number of flips:", m_stats.m_moves);
+        for (unsigned i = 0; i < g->size(); i++)
+            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+            {
+                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                NOT_IMPLEMENTED_YET();
+            }
+
+        if (m_produce_models) {
+            model_ref mdl = m_tracker.get_model();
+            mc = model2model_converter(mdl.get());
+            TRACE("sls_model", mc->display(tout););
+        }
+        g->reset();
+    }
+    else
+        mc = 0;
+}
+
+unsigned sls_engine::check_restart(unsigned curr_value)
+{
+    if (curr_value > m_restart_limit)
+    {
+#if _RESTART_SCHEME_ == 4
+        m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+#elif _RESTART_SCHEME_ == 3
+        m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 2
+        m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 1
+        if (m_stats.m_restarts & 1)
+            m_restart_limit += _RESTART_LIMIT_;
+        else
+            m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+#else
+        m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+        printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+        m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
+        return 0;
+    }
+    return 1;
+}
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
new file mode 100644
index 000000000..878354c6d
--- /dev/null
+++ b/src/tactic/sls/sls_engine.h
@@ -0,0 +1,159 @@
+/*++
+Copyright (c) 2014 Microsoft Corporation
+
+Module Name:
+
+    sls_engine.h
+
+Abstract:
+
+    A Stochastic Local Search (SLS) engine
+
+Author:
+
+    Christoph (cwinter) 2014-03-19
+
+Notes:
+
+--*/
+#ifndef _SLS_ENGINE_H_
+#define _SLS_ENGINE_H_
+
+#include"stopwatch.h"
+#include"lbool.h"
+#include"model_converter.h"
+
+#include"sls_compilation_settings.h"
+#include"sls_tracker.h"
+#include"sls_evaluator.h"
+
+class sls_engine {
+public:
+    class stats {
+    public:
+        unsigned        m_restarts;
+        stopwatch       m_stopwatch;
+        unsigned        m_full_evals;
+        unsigned        m_incr_evals;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+
+        stats() :
+            m_restarts(0),
+            m_full_evals(0),
+            m_incr_evals(0),
+            m_moves(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
+            m_flips(0),
+            m_incs(0),
+            m_decs(0),
+            m_invs(0) {
+            m_stopwatch.reset();
+            m_stopwatch.start();
+        }
+        void reset() {
+            m_full_evals = m_flips = m_incr_evals = 0;
+            m_stopwatch.reset();
+            m_stopwatch.start();
+        }
+    };
+
+protected:
+    ast_manager   & m_manager;
+    stats           m_stats;
+    unsynch_mpz_manager m_mpz_manager;
+    powers          m_powers;
+    mpz             m_zero, m_one, m_two;
+    bool            m_produce_models;
+    volatile bool   m_cancel;
+    bv_util         m_bv_util;
+    sls_tracker     m_tracker;
+    sls_evaluator   m_evaluator;
+
+    unsigned		m_restart_limit;
+    unsigned        m_max_restarts;
+    unsigned        m_plateau_limit;
+
+    ptr_vector<mpz> m_old_values;
+
+    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;
+
+public:    
+    sls_engine(ast_manager & m, params_ref const & p);
+    ~sls_engine();
+
+    ast_manager & m() const { return m_manager; }
+
+    void set_cancel(bool f) { m_cancel = f; }
+    void cancel() { set_cancel(true); }
+    void reset_cancel() { set_cancel(false); }
+
+    void updt_params(params_ref const & _p);
+
+    stats const & get_stats(void) { return m_stats; }
+    void reset_statistics(void) { m_stats.reset(); }    
+
+    bool full_eval(goal_ref const & g, model & mdl);
+    
+
+    void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
+    void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
+    void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result);
+    void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
+    void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
+    void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
+
+    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    
+    
+    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
+    
+    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    
+
+    lbool search(goal_ref const & g);    
+
+    void operator()(goal_ref const & g, model_converter_ref & mc);
+
+protected:
+    void checkpoint();
+    lbool search_old(goal_ref const & g);
+    double get_restart_armin(unsigned cnt_restarts);    
+
+    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                 double & best_score, unsigned & best_const, mpz & best_value);
+
+    bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                       double & best_score, unsigned & best_const, mpz & best_value);
+
+    double top_score(goal_ref const & g);
+    double rescore(goal_ref const & g);
+    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+
+#if _EARLY_PRUNE_
+    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
+#endif
+
+    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+
+    void mk_random_move(ptr_vector<func_decl> & unsat_constants);
+    void mk_random_move(goal_ref const & g);
+
+    bool handle_plateau(goal_ref const & g);
+    bool handle_plateau(goal_ref const & g, double old_score);
+
+    inline unsigned check_restart(unsigned curr_value);
+};
+
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 97860e3a2..8d2a7ba1d 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -20,6 +20,9 @@ Notes:
 #ifndef _SLS_EVALUATOR_H_
 #define _SLS_EVALUATOR_H_
 
+#include"model_evaluator.h"
+
+#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 #include"sls_tracker.h"
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 743ad00bc..0f157d3a6 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,1363 +16,31 @@ Author:
 Notes:
 
 --*/
-#include<iomanip>
-#include"map.h"
 #include"nnf.h"
-#include"cooperate.h"
-#include"ast_smt2_pp.h"
-#include"ast_pp.h"
-#include"var_subst.h"
-#include"model_pp.h"
-#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
-#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"stopwatch.h"
 #include"propagate_values_tactic.h"
-#include"sls_tactic.h"
+#include"ctx_simplify_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"nnf_tactic.h"
-#include"luby.h"
-#include "ctx_simplify_tactic.h"
-
-// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
-// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
-#define _BFS_ 0
-
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
-#define _FOCUS_ 1
-
-// probability of choosing the same assertion again in the next step
-#define _PERC_STICKY_ 0
-
-// do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 0
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
-// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 3.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// should score of discunctions be calculated by multiplication of the inverse score rather than min?
-#define _SCORE_OR_MUL_ 0
-
-// do we use some kind of variable neighbourhood-search?
-// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
-#define _VNS_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no
-// 1 = yes, by multiplying it with some factor
-// 2 = yes, by squaring it
-// 3 = yes, by setting it to zero
-// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.25
-
-// shall we toggle the weight after each restart?
-#define _WEIGHT_TOGGLE_ 0
-
-// do we use intensification steps in local minima? if so, how many?
-#define _INTENSIFICATION_ 0
-#define _INTENSIFICATION_TRIES_ 0
-
-// what is the percentage of random moves in plateaus (instead of full randomization)?
-#define _PERC_PLATEAU_MOVES_ 0
-
-// shall we repick clause when randomizing in a plateau or use the current one?
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 10.0
-
-// is uct clause selection probabilistic similar to variable selection in sparrow?
-// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
-#define _PROBABILISTIC_UCT_ 0
-
-// additive constants for probabilistic uct > 0
-#define _UCT_EPS_ 0.0001
-
-// shall we reset _UCT_ touched values after restart?
-#define _UCT_RESET_ 0
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 1
-
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
-// shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 0
-
-// shall we try multiplication by 3?
-#define _USE_MUL3_ 0
-
-// shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 0
-
-// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 0
-
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
-#define _REAL_RS_ 0
-#define _REAL_PBFS_ 0
-
-// how many bits do we neglect in each iteration?
-#define _SKIP_BITS_ 0
-
-// when randomizing local, what is the probability for changing a single bit?
-// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
-#define _PERC_CHANGE_ 0
-
-// do we use random steps for noise?
-// 0 = no, 1 = randomize local, 2 = make random move
-#define _TYPE_RSTEP_ 0
-
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
-
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-
-#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
-    InvalidConfiguration;
-#endif
-#if (_PROBABILISTIC_UCT_ && !_UCT_)
-    InvalidConfiguration;
-#endif
-#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
-    InvalidConfiguration;
-#endif
-#if (_PERC_CHANGE_ == 50)
-    InvalidConfiguration;
-#endif
-#if (_PERC_STICKY_ && !_FOCUS_)
-    InvalidConfiguration;
-#endif
+#include"stopwatch.h"
 
+#include"sls_tactic.h"
 #include"sls_params.hpp"
-#include"sls_evaluator.h"
-#include"sls_tracker.h"
+#include"sls_engine.h"
 
-class sls_tactic : public tactic {
-    class stats {
-    public:
-        unsigned        m_restarts;
-        stopwatch       m_stopwatch;    
-        unsigned        m_full_evals;
-        unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
-
-        stats() :
-            m_restarts(0),
-            m_full_evals(0),
-            m_incr_evals(0),
-            m_moves(0),
-            m_umins(0),
-            m_mul2s(0),
-            m_mul3s(0),
-            m_div2s(0),
-            m_flips(0),
-            m_incs(0),
-            m_decs(0),
-            m_invs(0) {
-                m_stopwatch.reset();
-                m_stopwatch.start();
-            }
-        void reset() {
-            m_full_evals = m_flips = m_incr_evals = 0;
-            m_stopwatch.reset();
-            m_stopwatch.start();
-        }
-    };    
-
-    struct imp {       
-        ast_manager   & m_manager;
-        stats         & m_stats;
-        unsynch_mpz_manager m_mpz_manager;
-        powers          m_powers;
-        mpz             m_zero, m_one, m_two;            
-        bool            m_produce_models;
-        volatile bool   m_cancel;    
-        bv_util         m_bv_util;
-        sls_tracker     m_tracker;
-        sls_evaluator   m_evaluator;
-
-        unsigned		m_restart_limit;
-        unsigned        m_max_restarts;
-        unsigned        m_plateau_limit;
-
-        ptr_vector<mpz> m_old_values;
-        
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
-
-        imp(ast_manager & m, params_ref const & p, stats & s) : 
-            m_manager(m),
-            m_stats(s),
-            m_powers(m_mpz_manager),
-            m_zero(m_mpz_manager.mk_z(0)),
-            m_one(m_mpz_manager.mk_z(1)),
-            m_two(m_mpz_manager.mk_z(2)),
-            m_cancel(false),
-            m_bv_util(m),
-            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
-            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
-        {
-            updt_params(p);
-        }
-
-        ~imp() {
-            m_mpz_manager.del(m_zero);
-            m_mpz_manager.del(m_one);
-            m_mpz_manager.del(m_two);
-        }        
-
-        double get_restart_armin(unsigned cnt_restarts)
-        {
-            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-            //printf("armin: %f\n", pow(1.1, inner_id + 1));
-            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
-        }
-
-        inline unsigned check_restart(unsigned curr_value)
-        {
-            if (curr_value > m_restart_limit)
-            {
-#if _RESTART_SCHEME_ == 4
-                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
-#elif _RESTART_SCHEME_ == 3
-                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 2
-                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 1
-                if (m_stats.m_restarts & 1)
-                    m_restart_limit += _RESTART_LIMIT_;
-                else
-                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
-#else
-                    m_restart_limit += _RESTART_LIMIT_;
-#endif
-#if _WEIGHT_TOGGLE_
-                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-#endif
-                return 0;
-            }
-            return 1;
-        }
-
-        ast_manager & m() const { return m_manager; }
-
-        void set_cancel(bool f) { m_cancel = f; }
-        void cancel() { set_cancel(true); }
-        void reset_cancel() { set_cancel(false); }
-
-        static void collect_param_descrs(param_descrs & r) {
-            sls_params::collect_param_descrs(r);
-        }
-
-        void updt_params(params_ref const & _p) {
-            sls_params p(_p);
-            m_produce_models = _p.get_bool("model", false);
-            m_max_restarts = p.restarts();            
-            m_tracker.set_random_seed(p.random_seed());
-            m_plateau_limit = p.plateau_limit();
-        }
-
-        void checkpoint() { 
-            if (m_cancel)
-                throw tactic_exception(TACTIC_CANCELED_MSG);
-            cooperate("sls");
-        }
-
-        bool full_eval(goal_ref const & g, model & mdl) {
-            bool res = true;
-
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz && res; i++) {
-                checkpoint();
-                expr_ref o(m_manager);
-
-                if (!mdl.eval(g->form(i), o, true))
-                    exit(ERR_INTERNAL_FATAL);
-
-                res = m_manager.is_true(o.get());
-            }        
-
-            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
-
-            return res;
-        }
-
-        double top_score(goal_ref const & g) {
-            #if 0
-            double min = m_tracker.get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
-                double q = m_tracker.get_score(g->form(i));
-                if (q < min) min = q;
-            }
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                for (unsigned i = 0; i < sz; i++)
-                                    tout << " " << m_tracker.get_score(g->form(i));
-                                tout << " MIN: " << min << std::endl; );
-            return min;
-            #else
-            double top_sum = 0.0;
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                top_sum += m_tracker.get_score(e);
-            }
-
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                    for (unsigned i = 0; i < sz; i++)
-                                        tout << " " << m_tracker.get_score(g->form(i));
-                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
-
-#if _CACHE_TOP_SCORE_
-            m_tracker.set_top_sum(top_sum);
-#endif
-
-            return top_sum / (double) sz;
-            #endif
-        }
-
-        double rescore(goal_ref const & g) {
-            m_evaluator.update_all();
-            m_stats.m_full_evals++;
-            return top_score(g);
-        }
-
-        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.serious_update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-#if _EARLY_PRUNE_
-        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_stats.m_incr_evals++;
-            if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
-                return (m_tracker.get_top_sum() / g->size());
-#else
-                return top_score(g);
-#endif
-            else
-                return 0.0;
-        }
-#endif
-
-        // checks whether the score outcome of a given move is better than the previous score
-        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-
-            #ifdef Z3DEBUG
-            mpz old_value;
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-            #endif
-
-#if _EARLY_PRUNE_
-            double r = incremental_score_prune(g, fd, temp);
-#else
-            double r = incremental_score(g, fd, temp);
-#endif   
-            #ifdef Z3DEBUG
-            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
-                                        " --> " << r << std::endl; );
-        
-            m_mpz_manager.del(old_value);
-            #endif
-
-//            if (r >= best_score) {
-            if (r > best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // same as what_if, but only applied to the score of a specific atom, not the total score
-        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-            m_evaluator.update(fd, temp);
-            double r = m_tracker.get_score(e);
-            if (r >= best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.add(old_value, add_value, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-
-        }
-
-        // Andreas: do we really need all those temporary mpzs?
-        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.mul(old_value, m_two, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-        }
-
-        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            m_mpz_manager.div(old_value, m_two, result);
-        }
-
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
-            unsigned shift;        
-            m_mpz_manager.add(old_value, m_one, incremented);
-            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
-                m_mpz_manager.set(incremented, m_zero);
-        }
-
-        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
-            if (m_mpz_manager.is_zero(old_value)) {
-                m_mpz_manager.set(decremented, m_powers(bv_sz));
-                m_mpz_manager.dec(decremented);
-            }
-            else
-                m_mpz_manager.sub(old_value, m_one, decremented);
-        }
-
-        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
-            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
-        }
-
-        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
-            m_mpz_manager.set(flipped, m_zero);
-
-            if (m_bv_util.is_bv_sort(s)) {
-                mpz mask;
-                m_mpz_manager.set(mask, m_powers(bit));
-                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
-                m_mpz_manager.del(mask);
-            }
-            else if (m_manager.is_bool(s))
-                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
-            else
-                NOT_IMPLEMENTED_YET();
-        }
-
-        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
-        {
-            unsigned rnd_mv = 0;
-            unsigned ucc = unsat_constants.size(); 
-            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
-            func_decl * fd = unsat_constants[rc];
-
-            mpz new_value;
-
-            sort * srt = fd->get_range();
-            if (m_manager.is_bool(srt))
-                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-            else
-            {
-#if _USE_ADDSUB_
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-                move_type mt = (move_type) rnd_mv;
-
-                // inversion doesn't make sense, let's do a flip instead.
-                if (mt == MV_INV) mt = MV_FLIP;
-#else
-                mt = MV_FLIP;
-#endif
-                unsigned bit = 0;
-
-                switch (mt)
-                {
-                    case MV_FLIP: {
-                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
-                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                    break;
-                }
-                case MV_INC: 
-                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_DEC: 
-                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_INV:
-                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                default:
-                    NOT_IMPLEMENTED_YET();
-                }
-
-                TRACE("sls", tout << "Randomization candidates: ";
-                             for (unsigned i = 0; i < unsat_constants.size(); i++)
-                                 tout << unsat_constants[i]->get_name() << ", ";
-                             tout << std::endl;
-                             tout << "Random move: ";
-                             switch (mt) {
-                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                             }
-                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-            }
-
-            m_evaluator.update(fd, new_value);            
-            m_mpz_manager.del(new_value);
-        }
-
-        void mk_random_move(goal_ref const & g) {
-            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
-        }
-
-        // will use VNS to ignore some possible moves and increase the flips per second
-        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz, max_bv_sz = 0;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-                    // try to flip lsb
-                    mk_flip(srt, old_value, 0, temp);                
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = 0;
-                        move = MV_FLIP;
-                    }
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-
-            // we can either check the condition once in the beginning or check it repeatedly after every bit
-#if _VNS_ == 1
-            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
-#else
-            if (new_score <= score)
-            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
-#endif
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // What would happen if we flipped bit #j ?                
-                if (j < bv_sz)
-                {
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-            mpz temp2;
-#endif
-            unsigned bv_sz;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-#if _SKIP_BITS_
-                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
-#else
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-#endif
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-#endif
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-#if _USE_UNARY_MINUS_
-                    mk_inc(bv_sz, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_UMIN;
-#endif
-
-#if _USE_MUL2DIV2_
-                    // try multiplication by 2
-                    mk_mul2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_MUL2;
-
-#if _USE_MUL3_
-                    // try multiplication by 3
-                    mk_add(bv_sz, old_value, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_MUL3;
-#endif
-
-                    // try division by 2
-                    mk_div2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_DIV2;
-#endif
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                // Andreas: does not hold anymore now that we use top level score caching
-                //SASSERT(check == score);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-#if _USE_MUL3_
-            m_mpz_manager.del(temp2);
-#endif
-            return new_score;
-        }        
-
-        // same as find_best_move but only considers the score of the current expression instead of the overall score
-        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz;
-            double new_score = m_tracker.get_score(e);
-            // Andreas: tie breaking not implemented yet
-            // double tie_score = top_score(g);
-            for (unsigned i = 0; i < to_evaluate.size(); i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz; j++) {
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-                }
-
-                // reset to what it was before
-                m_evaluator.update(fd, old_value);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // first try of intensification ... does not seem to be efficient
-        bool handle_plateau(goal_ref const & g)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned pos = m_stats.m_moves % sz;
-#else
-            unsigned pos = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-            {
-                m_tracker.get_value(to_evaluate[i]);
-                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-            }            
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-            {
-                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
-                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    // Andreas: Actually this should never happen.
-                    NOT_IMPLEMENTED_YET();
-                } else {
-                    m_stats.m_moves++;
-                    func_decl * fd = to_evaluate[new_const];
-
-                    switch (move) {
-                    case MV_FLIP: m_stats.m_flips++; break;
-                    case MV_INC: m_stats.m_incs++; break;
-                    case MV_DEC: m_stats.m_decs++; break;
-                    case MV_INV: m_stats.m_invs++; break;
-                    case MV_UMIN: m_stats.m_umins++; break;
-                    case MV_MUL2: m_stats.m_mul2s++; break;
-                    case MV_MUL3: m_stats.m_mul3s++; break;
-                    case MV_DIV2: m_stats.m_div2s++; break;
-                    }
-                    
-                    m_evaluator.update(fd, new_value);
-                }
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
-
-            m_old_values.reset();
-
-            return 0;
-        }
-
-        // what_if version needed in the context of 2nd intensification try, combining local and global score
-        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
-                        double & best_score, mpz & best_value, unsigned i) {
-        
-            double global_score = incremental_score(g, fd, temp);
-            double local_score = m_tracker.get_score(e);
-            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
-
-            if (new_score >= best_score) {
-                best_score = new_score;
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // find_best_move version needed in the context of 2nd intensification try
-        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-        {
-            mpz old_value, temp;
-            double best_score = 0;
-
-            sort * srt = fd->get_range();
-            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
-                mk_flip(srt, old_value, j, temp);                
-                what_if(g, e, fd, temp, best_score, best_value, i); 
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-
-            return best_score;
-        }        
-
-        // second try to use intensification ... also not very effective
-        bool handle_plateau(goal_ref const & g, double old_score)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned new_const = m_stats.m_moves % sz;
-#else
-            unsigned new_const = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-
-            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-            func_decl * fd = to_evaluate[new_const];
-
-            mpz new_value;
-            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-            unsigned new_bit = 0;        
-            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-            
-            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-            {
-                new_score = find_best_move_local(g, q, fd, new_value, i);
-
-                m_stats.m_moves++;
-                m_stats.m_flips++;
-
-                global_score = incremental_score(g, fd, new_value);
-                local_score = m_tracker.get_score(q);
-
-                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            return 0;
-        }
-
-        // main search loop
-        lbool search(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            unsigned plateau_cnt = 0;
-
-            score = rescore(g);
-            unsigned sz = g->size();
-#if _PERC_STICKY_
-            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-
-#if _RESTARTS_ == 1
-            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 2
-            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 3
-            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#endif
-                checkpoint();
-                m_stats.m_moves++;
-
-#if _REAL_RS_ || _REAL_PBFS_
-                //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
-
-#if _FOCUS_
-#if _PERC_STICKY_
-                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
-                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#else
-                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-                if (!e)
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
-                if (!to_evaluate.size())
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-#endif
-
-#if _TYPE_RSTEP_
-                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                {
-#if _TYPE_RSTEP_ == 1
-                    m_evaluator.randomize_local(to_evaluate);
-#elif _TYPE_RSTEP_ == 2
-                    mk_random_move(to_evaluate);
-#endif
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                }
-                continue;
-#endif
-
-#if _WEIGHT_DIST_ == 4
-                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif       
-                old_score = score;
-                new_const = (unsigned)-1;
-
-#if _VNS_
-                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    score = old_score;
-                    plateau_cnt++;
-#if _INTENSIFICATION_
-                    handle_plateau(g, score);
-                    //handle_plateau(g);
-                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-#if _PERC_PLATEAU_MOVES_
-                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
-                        mk_random_move(to_evaluate);
-                    else
-#endif
-#if _REPICK_
-                    m_evaluator.randomize_local(g, m_stats.m_moves);
-#else
-                    m_evaluator.randomize_local(to_evaluate);
-#endif
-#endif
-
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                } else {
-                    func_decl * fd = to_evaluate[new_const];              
-#if _REAL_RS_ || _REAL_PBFS_
-                    score = serious_score(g, fd, new_value);
-#else
-                    score = incremental_score(g, fd, new_value);    
-#endif
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        // main search loop
-        lbool search_old(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            
-            score = rescore(g);
-            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-                         tout << "Score distribution:"; 
-                         for (unsigned i = 0; i < g->size(); i++)
-                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                         tout << " TOP: " << score << std::endl; ); 
-        
-            unsigned plateau_cnt = 0;
-
-            // Andreas: Why do we only allow so few plateaus?
-#if _RESTARTS_
-            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
-            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
-#endif
-                do {
-                    checkpoint();
-
-#if _WEIGHT_DIST_ == 4
-                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-            
-#if _TYPE_RSTEP_
-                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                    {
-#if _TYPE_RSTEP_ == 1
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _TYPE_RSTEP_ == 2
-                        mk_random_move(g);
-#endif
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                            } else
-                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                        }
-                    }
-#endif
-                    old_score = score;
-                    new_const = (unsigned)-1;
-                        
-                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-                    if (!to_evaluate.size())
-                    {
-                        res = l_true;
-                        goto bailout;
-                    }
-                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
-                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
-                                                tout << to_evaluate[i]->get_name() << std::endl; );
-
-#if _VNS_
-                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-                    if (new_const == static_cast<unsigned>(-1)) {
-                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
-                                        for (unsigned i = 0; i < g->size(); i++) {
-                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
-                                        });
-
-                        TRACE("sls_max", m_tracker.show_model(tout);
-                                        tout << "Scores: " << std::endl;
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
-                                            m_tracker.get_score(g->form(i)) << std::endl; );
-                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
-                        score = old_score;
-                    }
-                    else {
-                        // Andreas: Why does randomizing not count as a move? (Now it does.)
-                        m_stats.m_moves++;
-                        func_decl * fd = to_evaluate[new_const];
-
-                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
-                                        switch (move) {
-                                        case MV_FLIP:  
-                                            tout << "Flip";
-                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
-                                            break;
-                                        case MV_INC: 
-                                            tout << "+1";
-                                            break;
-                                        case MV_DEC: 
-                                            tout << "-1";
-                                            break;
-                                        case MV_INV: 
-                                            tout << "NEG";
-                                            break;
-                                        };                                        
-                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
-
-                        switch (move) {
-                        case MV_FLIP: m_stats.m_flips++; break;
-                        case MV_INC: m_stats.m_incs++; break;
-                        case MV_DEC: m_stats.m_decs++; break;
-                        case MV_INV: m_stats.m_invs++; break;
-                        case MV_UMIN: m_stats.m_umins++; break;
-                        case MV_MUL2: m_stats.m_mul2s++; break;
-                        case MV_MUL3: m_stats.m_mul3s++; break;
-                        case MV_DIV2: m_stats.m_div2s++; break;
-                        }
-                    
-#if _REAL_RS_ || _REAL_PBFS_
-                        score = serious_score(g, fd, new_value);
-#else
-                        score = incremental_score(g, fd, new_value);    
-#endif
-
-                        TRACE("sls", tout << "Score distribution:"; 
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                                        tout << " TOP: " << score << std::endl; );                        
-                    }
-
-                    if (score >= 0.99999) {
-//                    if (score >= 1.0) {
-                        // score could theoretically be imprecise.
-                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
-                        bool all_true = true;
-                        for (unsigned i = 0; i < g->size() && all_true; i++)
-                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                all_true=false;
-                        if (all_true) {
-                            res = l_true; // sat
-                            goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                    /*
-                    if (m_stats.m_moves % 100 == 0)
-                    {
-                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-                    }*/
-                }
-                while (score > old_score && res == l_undef);                
-                
-                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
-                if (score != old_score) {
-                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
-                    plateau_cnt = 0;
-                } else {
-                    m_stats.m_moves++;
-                    plateau_cnt++;
-                    //report_tactic_progress("Plateau.", plateau_cnt);
-                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
-                    //if (plateau_cnt < m_plateau_limit) {
-                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
-#if _INTENSIFICATION_
-                        handle_plateau(g, score);
-                        //handle_plateau(g);
-#else
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#endif
-                        //mk_random_move(g);
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        void operator()(goal_ref const & g, model_converter_ref & mc) {
-            if (g->inconsistent()) {
-                mc = 0;
-                return;
-            }
-
-            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
-            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
-            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
-            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
-            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-            
-#if _WEIGHT_DIST_ == 4
-            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-            m_tracker.initialize(g);
-            lbool res = l_undef;
-        
-            m_restart_limit = _RESTART_LIMIT_;
-
-            do {
-                checkpoint();
-
-                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                res = search(g);
-
-                if (res == l_undef)
-                {
-#if _RESTART_INIT_
-                    m_tracker.randomize(g);
-#else
-                    m_tracker.reset(g);
-#endif
-                }
-            }
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-        
-            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-            if (res == l_true) {    
-                report_tactic_progress("Number of flips:", m_stats.m_moves);
-                for (unsigned i = 0; i < g->size(); i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                    {
-                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                        NOT_IMPLEMENTED_YET(); 
-                    }
-
-                if (m_produce_models) {
-                    model_ref mdl = m_tracker.get_model();
-                    mc = model2model_converter(mdl.get());
-                    TRACE("sls_model", mc->display(tout); );
-                }
-                g->reset();
-            }
-            else
-                mc = 0;
-        }
-    };
-    
+class sls_tactic : public tactic {    
     ast_manager    & m;
     params_ref       m_params;
-    imp            * m_imp;
-    stats            m_stats;
+    sls_engine     * m_engine;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_imp = alloc(imp, m, p, m_stats);
+        m_engine = alloc(sls_engine, m, p);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -1380,16 +48,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_imp);
+        dealloc(m_engine);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_imp->updt_params(p);
+        m_engine->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        imp::collect_param_descrs(r);
+        sls_params::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -1397,14 +65,13 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());
-        m_imp->m_produce_models = g->models_enabled();        
+        SASSERT(g->is_well_sorted());        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_imp->operator()(g, mc);
+        m_engine->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -1413,40 +80,41 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = m_imp;
+        sls_engine * d = m_engine;
         #pragma omp critical (tactic_cancel)
         {
-            d = m_imp;
+            d = m_engine;
         }
         dealloc(d);
-        d = alloc(imp, m, m_params, m_stats);
+        d = alloc(sls_engine, m, m_params);
         #pragma omp critical (tactic_cancel) 
         {
-            m_imp = d;
+            m_engine = d;
         }
     }
     
     virtual void collect_statistics(statistics & st) const {
-        double seconds = m_stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", m_stats.m_restarts);
-        st.update("sls full evals", m_stats.m_full_evals);
-        st.update("sls incr evals", m_stats.m_incr_evals);
-        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
-        st.update("sls FLIP moves", m_stats.m_flips);    
-        st.update("sls INC moves", m_stats.m_incs);
-        st.update("sls DEC moves", m_stats.m_decs);
-        st.update("sls INV moves", m_stats.m_invs);
-        st.update("sls moves", m_stats.m_moves);
-        st.update("sls moves/sec", m_stats.m_moves / seconds);
+        sls_engine::stats const & stats = m_engine->get_stats();
+        double seconds = stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", stats.m_restarts);
+        st.update("sls full evals", stats.m_full_evals);
+        st.update("sls incr evals", stats.m_incr_evals);
+        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
+        st.update("sls FLIP moves", stats.m_flips);
+        st.update("sls INC moves", stats.m_incs);
+        st.update("sls DEC moves", stats.m_decs);
+        st.update("sls INV moves", stats.m_invs);
+        st.update("sls moves", stats.m_moves);
+        st.update("sls moves/sec", stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_stats.reset();
+        m_engine->reset_statistics();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_imp)
-            m_imp->set_cancel(f);
+        if (m_engine)
+            m_engine->set_cancel(f);
     }
 };
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 4d9c078b6..7d1d4c0f1 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,6 +20,12 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
+#include"goal.h"
+#include"model.h"
+
+#include"sls_compilation_settings.h"
+#include"sls_powers.h"
+
 class sls_tracker {
     ast_manager         & m_manager;
     unsynch_mpz_manager & m_mpz_manager;
@@ -1187,7 +1193,7 @@ public:
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); 
 #elif _UCT_ == 2
                 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif
@@ -1335,7 +1341,7 @@ public:
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif

From e3ae0ba0bd67b40944efc9afacc65d5eacc024d5 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 17:26:05 +0000
Subject: [PATCH 007/108] SLS refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index aea4787b0..8e52596e0 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -18,6 +18,10 @@ Notes:
     This file should go away completely once we have evaluated all options.
 
 --*/
+
+#ifndef _SLS_COMPILATION_SETTINGS_H_
+#define _SLS_COMPILATION_SETTINGS_H_
+
 // which unsatisfied assertion is selected? only works with _FOCUS_ > 0
 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
 #define _BFS_ 0
@@ -155,4 +159,6 @@ InvalidConfiguration;
 #endif
 #if (_PERC_STICKY_ && !_FOCUS_)
 InvalidConfiguration;
+#endif
+
 #endif
\ No newline at end of file

From c615bc0c34fa3646e0312c89e5fd7f0ce51efbe7 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Thu, 20 Mar 2014 15:58:53 +0000
Subject: [PATCH 008/108] uct forget and minisat restarts added

---
 src/tactic/sls/sls_tactic.cpp | 31 +++++++++++++++++++++++--------
 src/tactic/sls/sls_tracker.h  | 22 ++++++++++++++++++++--
 2 files changed, 43 insertions(+), 10 deletions(-)

diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 743ad00bc..b2b7035e0 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -49,7 +49,7 @@ Notes:
 #define _PERC_STICKY_ 0
 
 // do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 0
+#define _DIRTY_UP_ 1
 
 // do we use restarts?
 // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
@@ -58,10 +58,10 @@ Notes:
 #define _RESTART_LIMIT_ 10
 // 0 = initialize with all zero, 1 initialize with random value
 #define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
 #define _RESTART_SCHEME_ 1
 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 3.0
+#define _RESTART_CONST_ARMIN_ 4.0
 
 // timelimit
 #define _TIMELIMIT_ 3600
@@ -85,7 +85,7 @@ Notes:
 #define _WEIGHT_DIST_ 1
 
 // the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.25
+#define _WEIGHT_DIST_FACTOR_ 0.5
 
 // shall we toggle the weight after each restart?
 #define _WEIGHT_TOGGLE_ 0
@@ -104,7 +104,7 @@ Notes:
 #define _UCT_ 1
 
 // how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 10.0
+#define _UCT_CONSTANT_ 20.0
 
 // is uct clause selection probabilistic similar to variable selection in sparrow?
 // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
@@ -116,9 +116,13 @@ Notes:
 // shall we reset _UCT_ touched values after restart?
 #define _UCT_RESET_ 0
 
+// do we gradually reduce the touched values of _UCT_?
+#define _UCT_FORGET_ 0
+#define _UCT_FORGET_FACTOR_ 0.5
+
 // how shall we initialize the _UCT_ total touched counter?
 // 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 1
+#define _UCT_INIT_ 0
 
 // shall we use addition/subtraction?
 #define _USE_ADDSUB_ 1
@@ -265,7 +269,9 @@ class sls_tactic : public tactic {
         {
             if (curr_value > m_restart_limit)
             {
-#if _RESTART_SCHEME_ == 4
+#if _RESTART_SCHEME_ == 5
+                m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+#elif _RESTART_SCHEME_ == 4
                 m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
                 m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
@@ -976,6 +982,11 @@ class sls_tactic : public tactic {
                 checkpoint();
                 m_stats.m_moves++;
 
+#if _UCT_FORGET_
+                if (m_stats.m_moves % _UCT_FORGET_ == 0)
+                    m_tracker.uct_forget(g);
+#endif
+
 #if _REAL_RS_ || _REAL_PBFS_
                 //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
@@ -1277,11 +1288,13 @@ class sls_tactic : public tactic {
 
             verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
             verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl;
             verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
             verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
             verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
             verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
             verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
+            verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl;
             verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
             verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
             verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
@@ -1296,6 +1309,8 @@ class sls_tactic : public tactic {
             verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
             verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
             verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+            verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
+            verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
             verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
             verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
             verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
@@ -1495,7 +1510,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                         // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
                         //mk_ctx_simplify_tactic(m, ctx_p),
                         // Andreas: This one at least eliminates top level duplicates ...
-                        mk_simplify_tactic(m),
+                        //mk_simplify_tactic(m),
                         // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 4d9c078b6..45e1719d2 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -270,6 +270,20 @@ public:
     }
 #endif
 
+    void uct_forget(goal_ref const & g) {
+        expr * e;
+        unsigned touched_old, touched_new;
+
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            e = g->form(i);
+            touched_old = m_scores.find(e).touched;
+            touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
+            m_scores.find(e).touched = touched_new;
+            m_touched += touched_new - touched_old;
+        }
+    }
+
     void initialize(app * n) {
         // Build score table
         if (!m_scores.contains(n)) {
@@ -1190,6 +1204,8 @@ public:
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
 #elif _UCT_ == 2
                 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#elif _UCT_ == 3
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
                 if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
@@ -1197,7 +1213,7 @@ public:
             if (pos == static_cast<unsigned>(-1))
                 return m_temp_constants;
 
-#if _UCT_ == 1
+#if _UCT_ == 1 || _UCT_ == 3
             m_scores.find(g->form(pos)).touched++;
             m_touched++;
 #elif _UCT_ == 2
@@ -1338,6 +1354,8 @@ public:
             double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#elif _UCT_ == 3
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
             if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
@@ -1345,7 +1363,7 @@ public:
         if (pos == static_cast<unsigned>(-1))
             return 0;
 
-#if _UCT_ == 1
+#if _UCT_ == 1 || _UCT_ == 3
         m_scores.find(g->form(pos)).touched++;
         m_touched++;
 #elif _UCT_ == 2

From 6f9a348f6398cecd0852f2d74d4d25ebb4d670fc Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 26 Mar 2014 17:26:06 +0000
Subject: [PATCH 009/108] removed dependency of bvsls on goal_refs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp  | 219 +++++++++++++++++++--------------
 src/tactic/sls/sls_engine.h    |  58 ++++-----
 src/tactic/sls/sls_evaluator.h |   4 +-
 src/tactic/sls/sls_tracker.h   |  84 ++++++-------
 4 files changed, 195 insertions(+), 170 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 92471aad8..9fa2cc263 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -74,15 +74,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
+bool sls_engine::full_eval(model & mdl) {
     bool res = true;
 
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(g->form(i), o, true))
+        if (!mdl.eval(m_assertions[i], o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -93,7 +93,7 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     return res;
 }
 
-double sls_engine::top_score(goal_ref const & g) {
+double sls_engine::top_score() {
 #if 0
     double min = m_tracker.get_score(g->form(0));
     unsigned sz = g->size();
@@ -108,15 +108,15 @@ double sls_engine::top_score(goal_ref const & g) {
     return min;
 #else
     double top_sum = 0.0;
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = g->form(i);
+        expr * e = m_assertions[i];
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(g->form(i));
+        tout << " " << m_tracker.get_score(m_assertions[i]);
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
 #if _CACHE_TOP_SCORE_
@@ -127,40 +127,40 @@ double sls_engine::top_score(goal_ref const & g) {
 #endif
 }
 
-double sls_engine::rescore(goal_ref const & g) {
+double sls_engine::rescore() {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score(g);
+    return top_score();
 }
 
-double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
+    return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-    return top_score(g);
+    return top_score();
 #endif
 }
 
-double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
+    return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-    return top_score(g);
+    return top_score();
 #endif
 }
 
-double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
 #if _EARLY_PRUNE_
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-        return (m_tracker.get_top_sum() / g->size());
+        return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-        return top_score(g);
+        return top_score();
 #endif
     else
         return 0.0;
@@ -170,8 +170,13 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c
 }
 
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if(
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
@@ -179,9 +184,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 #endif
 
 #if _EARLY_PRUNE_
-    double r = incremental_score_prune(g, fd, temp);
+    double r = incremental_score_prune(fd, temp);
 #else
-    double r = incremental_score(g, fd, temp);
+    double r = incremental_score(fd, temp);
 #endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
@@ -202,8 +207,15 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 }
 
 // same as what_if, but only applied to the score of a specific atom, not the total score
-bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                    double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if_local(
+    expr * e, 
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) 
+{
     m_evaluator.update(fd, temp);
     double r = m_tracker.get_score(e);
     if (r >= best_score) {
@@ -344,13 +356,19 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     m_mpz_manager.del(new_value);
 }
 
-void sls_engine::mk_random_move(goal_ref const & g) {
-    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
+void sls_engine::mk_random_move() {
+    mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves));
 }
 
 // will use VNS to ignore some possible moves and increase the flips per second
-double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move_vns(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
     unsigned bv_sz, max_bv_sz = 0;
     double new_score = score;
@@ -366,31 +384,31 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
             // try to flip lsb
             mk_flip(srt, old_value, 0, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = 0;
                 move = MV_FLIP;
             }
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         SASSERT(check == score);
     }
 
@@ -412,13 +430,13 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
                 {
                     mk_flip(srt, old_value, j, temp);
 
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                    if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                         new_bit = j;
                         move = MV_FLIP;
                     }
                 }
                 // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
+                double check = incremental_score(fd, old_value);
                 SASSERT(check == score);
             }
     m_mpz_manager.del(old_value);
@@ -427,8 +445,14 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
 }
 
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
     mpz temp2;
@@ -451,7 +475,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
@@ -462,19 +486,19 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
 #if _USE_UNARY_MINUS_
@@ -504,7 +528,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         // Andreas: does not hold anymore now that we use top level score caching
         //SASSERT(check == score);
     }
@@ -572,15 +596,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_eva
 }
 
 // first try of intensification ... does not seem to be efficient
-bool sls_engine::handle_plateau(goal_ref const & g)
+bool sls_engine::handle_plateau()
 {
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
 #if _BFS_
     unsigned pos = m_stats.m_moves % sz;
 #else
     unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+    expr * e = m_tracker.get_unsat_assertion(sz, pos);
     if (!e)
         return 0;
 
@@ -634,10 +658,15 @@ bool sls_engine::handle_plateau(goal_ref const & g)
 }
 
 // what_if version needed in the context of 2nd intensification try, combining local and global score
-bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                double & best_score, mpz & best_value, unsigned i) {
-
-    double global_score = incremental_score(g, fd, temp);
+bool sls_engine::what_if(
+    expr * e, 
+    func_decl * fd, 
+    const mpz & temp,
+    double & best_score, 
+    mpz & best_value, 
+    unsigned i) 
+{
+    double global_score = incremental_score(fd, temp);
     double local_score = m_tracker.get_score(e);
     double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
@@ -651,7 +680,7 @@ bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz
 }
 
 // find_best_move version needed in the context of 2nd intensification try
-double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i)
 {
     mpz old_value, temp;
     double best_score = 0;
@@ -662,7 +691,7 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl
 
     for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
         mk_flip(srt, old_value, j, temp);
-        what_if(g, e, fd, temp, best_score, best_value, i);
+        what_if(e, fd, temp, best_score, best_value, i);
     }
 
     m_mpz_manager.del(old_value);
@@ -672,15 +701,15 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl
 }
 
 // second try to use intensification ... also not very effective
-bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
+bool sls_engine::handle_plateau(double old_score)
 {
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
 #if _BFS_
     unsigned new_const = m_stats.m_moves % sz;
 #else
     unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+    expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const);
     if (!e)
         return 0;
 
@@ -697,12 +726,12 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 
     for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
     {
-        new_score = find_best_move_local(g, q, fd, new_value, i);
+        new_score = find_best_move_local(q, fd, new_value, i);
 
         m_stats.m_moves++;
         m_stats.m_flips++;
 
-        global_score = incremental_score(g, fd, new_value);
+        global_score = incremental_score(fd, new_value);
         local_score = m_tracker.get_score(q);
 
         SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
@@ -715,7 +744,7 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 }
 
 // main search loop
-lbool sls_engine::search(goal_ref const & g) {
+lbool sls_engine::search() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
@@ -723,8 +752,8 @@ lbool sls_engine::search(goal_ref const & g) {
     move_type move;
     unsigned plateau_cnt = 0;
 
-    score = rescore(g);
-    unsigned sz = g->size();
+    score = rescore();
+    unsigned sz = m_assertions.size();
 #if _PERC_STICKY_
     expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
@@ -750,7 +779,7 @@ lbool sls_engine::search(goal_ref const & g) {
         if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
             e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #else
-        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+        expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves);
 #endif
         if (!e)
         {
@@ -793,7 +822,7 @@ lbool sls_engine::search(goal_ref const & g) {
 #if _VNS_
         score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
 
         if (new_const == static_cast<unsigned>(-1)) {
@@ -811,14 +840,14 @@ lbool sls_engine::search(goal_ref const & g) {
             else
 #endif
 #if _REPICK_
-                m_evaluator.randomize_local(g, m_stats.m_moves);
+                m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
 #else
                 m_evaluator.randomize_local(to_evaluate);
 #endif
 #endif
 
 #if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / g->size();
+            score = m_tracker.get_top_sum() / m_assertions.size();
 #else
             score = top_score(g);
 #endif
@@ -828,7 +857,7 @@ lbool sls_engine::search(goal_ref const & g) {
 #if _REAL_RS_ || _REAL_PBFS_
             score = serious_score(g, fd, new_value);
 #else
-            score = incremental_score(g, fd, new_value);
+            score = incremental_score(fd, new_value);
 #endif
         }
     }
@@ -840,18 +869,18 @@ bailout:
 }
 
 // main search loop
-lbool sls_engine::search_old(goal_ref const & g) {
+lbool sls_engine::search_old() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
     mpz new_value;
     move_type move;
 
-    score = rescore(g);
+    score = rescore();
     TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
     tout << "Score distribution:";
-    for (unsigned i = 0; i < g->size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    for (unsigned i = 0; i < m_assertions.size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
     tout << " TOP: " << score << std::endl;);
 
     unsigned plateau_cnt = 0;
@@ -897,7 +926,7 @@ lbool sls_engine::search_old(goal_ref const & g) {
             old_score = score;
             new_const = (unsigned)-1;
 
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves);
             if (!to_evaluate.size())
             {
                 res = l_true;
@@ -908,22 +937,22 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 tout << to_evaluate[i]->get_name() << std::endl;);
 
 #if _VNS_
-            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
             if (new_const == static_cast<unsigned>(-1)) {
                 TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++) {
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                for (unsigned i = 0; i < m_assertions.size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
+                        tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl;
                 });
 
                 TRACE("sls_max", m_tracker.show_model(tout);
                 tout << "Scores: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
-                    m_tracker.get_score(g->form(i)) << std::endl;);
+                for (unsigned i = 0; i < m_assertions.size(); i++)
+                    tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " <<
+                    m_tracker.get_score(m_assertions[i]) << std::endl;);
                 // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                 score = old_score;
             }
@@ -962,14 +991,14 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 }
 
 #if _REAL_RS_ || _REAL_PBFS_
-                score = serious_score(g, fd, new_value);
+                score = serious_score(fd, new_value);
 #else
-                score = incremental_score(g, fd, new_value);
+                score = incremental_score(fd, new_value);
 #endif
 
                 TRACE("sls", tout << "Score distribution:";
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                for (unsigned i = 0; i < m_assertions.size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
                 tout << " TOP: " << score << std::endl;);
             }
 
@@ -978,8 +1007,8 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 // score could theoretically be imprecise.
                 // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                 bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1010,17 +1039,17 @@ lbool sls_engine::search_old(goal_ref const & g) {
             TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
 #if _INTENSIFICATION_
             handle_plateau(g, score);
-            //handle_plateau(g);
+            //handle_plateau();
 #else
-            m_evaluator.randomize_local(g, m_stats.m_moves);
+            m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
 #endif
-            //mk_random_move(g);
-            score = top_score(g);
+            //mk_random_move();
+            score = top_score();
 
             if (score >= 1.0) {
                 bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1046,6 +1075,10 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
+    for (unsigned i = 0; i < g->size(); i++)
+        assert_expr(g->form(i));
+    
+
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
     verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
@@ -1089,7 +1122,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 #if _WEIGHT_TOGGLE_
     m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
 #endif
-    m_tracker.initialize(g);
+    m_tracker.initialize(m_assertions);
     lbool res = l_undef;
 
     m_restart_limit = _RESTART_LIMIT_;
@@ -1098,14 +1131,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         checkpoint();
 
         report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search(g);
+        res = search();
 
         if (res == l_undef)
         {
 #if _RESTART_INIT_
-            m_tracker.randomize(g);
+            m_tracker.randomize();
 #else
-            m_tracker.reset(g);
+            m_tracker.reset(m_assertions);
 #endif
         }
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 878354c6d..8458817b6 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -71,6 +71,7 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
+    ptr_vector<expr> m_assertions;
 
     unsigned		m_restart_limit;
     unsigned        m_max_restarts;
@@ -92,11 +93,12 @@ public:
 
     void updt_params(params_ref const & _p);
 
+    void assert_expr(expr * e) { m_assertions.push_back(e); }
+
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(goal_ref const & g, model & mdl);
-    
+    bool full_eval(model & mdl);
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
     void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
@@ -104,54 +106,44 @@ public:
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
-    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    
-    
-    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                 double & best_score, mpz & best_value, unsigned i);
-    
-    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
-    
-
-    lbool search(goal_ref const & g);    
+    lbool search(void);    
 
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
-    lbool search_old(goal_ref const & g);
+    lbool search_old(void);
     double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
-
+    bool what_if(expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
     bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                        double & best_score, unsigned & best_const, mpz & best_value);
 
-    double top_score(goal_ref const & g);
-    double rescore(goal_ref const & g);
-    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
-    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double top_score();
+    double rescore();
+    double serious_score(func_decl * fd, const mpz & new_value);
+    double incremental_score(func_decl * fd, const mpz & new_value);
 
 #if _EARLY_PRUNE_
-    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score_prune(func_decl * fd, const mpz & new_value);
 #endif
-
-    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-
+    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
+    double find_best_move_vns(ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
-    void mk_random_move(goal_ref const & g);
+    void mk_random_move();
 
-    bool handle_plateau(goal_ref const & g);
-    bool handle_plateau(goal_ref const & g, double old_score);
+    bool handle_plateau(void);
+    bool handle_plateau(double old_score);
 
     inline unsigned check_restart(unsigned curr_value);
 };
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 8d2a7ba1d..0053763bb 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -922,8 +922,8 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-     void randomize_local(goal_ref const & g, unsigned int flip) {
-        randomize_local(m_tracker.get_unsat_constants(g, flip));
+    void randomize_local(ptr_vector<expr> const & as, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(as, flip));
     } 
 };
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 6ac054246..1b451e8fd 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,7 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"goal.h"
+#include"bv_decl_plugin.h"
 #include"model.h"
 
 #include"sls_compilation_settings.h"
@@ -365,12 +365,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(goal_ref const & g) {
+    void calculate_expr_distances(ptr_vector<expr> const & as) {
         // precondition: m_scores is set up.
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(g->form(i)));
+            stack.push_back(to_app(as[i]));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -418,12 +418,12 @@ public:
         quick_for_each_expr(ffd_proc, visited, e);
     }
 
-    void initialize(goal_ref const & g) {
+    void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
             else
@@ -438,7 +438,7 @@ public:
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
             initialize_recursive(e);
@@ -450,7 +450,7 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(g);
+        calculate_expr_distances(as);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
@@ -465,11 +465,11 @@ public:
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-            setup_occs(g->form(i));
+            setup_occs(as[i]);
 #endif
 
 #if _UCT_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
 #endif
     }
 
@@ -606,7 +606,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(goal_ref const & g) {
+    void randomize(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -620,13 +620,13 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
+        for (unsigned i = 0; i < as.size(); i++)
+            m_scores.find(as[i]).touched = 1;
 #endif
     }              
 
-    void reset(goal_ref const & g) {
+    void reset(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -636,9 +636,9 @@ public:
         }
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
+        for (unsigned i = 0; i < as.size(); i++)
+            m_scores.find(as[i]).touched = 1;
 #endif
     }              
 
@@ -1029,13 +1029,13 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as, unsigned sz) {
         if (sz == 1)
             return get_constants();
         m_temp_constants.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * q = g->form(i);
+            expr * q = as[i];
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -1049,22 +1049,22 @@ public:
         return m_temp_constants;
     }
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
             for (unsigned i = pos; i < sz; i++) {
-                expr * q = g->form(i);
+                expr * q = as[i];
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
+                expr * q = as[i];
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             return 0;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-            expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(as, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
             if (!q)
                 return m_temp_constants;
@@ -1141,19 +1141,19 @@ public:
             return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-        expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(as, sz, pos);
         if (!q)
             return m_temp_constants;
 
         return go_deeper(q);
     }
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
+    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as, unsigned int flip) {
+        unsigned sz = as.size();
 
         if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            if (m_mpz_manager.eq(get_value(as[0]), m_one))
                 return m_temp_constants;
             else
                 return get_constants();
@@ -1202,7 +1202,7 @@ public:
 #else
             double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1220,12 +1220,12 @@ public:
                 return m_temp_constants;
 
 #if _UCT_ == 1 || _UCT_ == 3
-            m_scores.find(g->form(pos)).touched++;
+            m_scores.find(as[pos]).touched++;
             m_touched++;
 #elif _UCT_ == 2
-            m_scores.find(g->form(pos)).touched = flip; 
+            m_scores.find(as[pos]).touched = flip; 
 #endif
-            expr * e = g->form(pos);
+            expr * e = as[pos];
 //            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
@@ -1304,11 +1304,11 @@ public:
     }
     
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
+    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned int flip) {
+        unsigned sz = as.size();
 
         if (sz == 1)
-            return g->form(0);
+            return as[0];
 
         m_temp_constants.reset();
 #if _FOCUS_ == 1
@@ -1352,7 +1352,7 @@ public:
 #else
         double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1370,13 +1370,13 @@ public:
             return 0;
 
 #if _UCT_ == 1 || _UCT_ == 3
-        m_scores.find(g->form(pos)).touched++;
+        m_scores.find(as[pos]).touched++;
         m_touched++;
 #elif _UCT_ == 2
         m_scores.find(g->form(pos)).touched = flip; 
 #endif
 //        return m_list_false[pos];
-        return g->form(pos);
+        return as[pos];
 
 #elif _BFS_ == 3
         unsigned int pos = -1;
@@ -1430,7 +1430,7 @@ public:
         unsigned int pos = get_random_uint(16) % sz;
         return get_unsat_assertion(g, sz, pos);
 #endif
-        return g->form(pos);
+        return as[pos];
 #elif _FOCUS_ == 2
 #if _BFS_
         unsigned int pos = flip % sz;

From be2066a1a63158d2087fa9ee33d537c28dd52af5 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 27 Mar 2014 13:34:21 +0000
Subject: [PATCH 010/108] disabled old code

---
 src/tactic/sls/sls_engine.cpp | 4 +++-
 src/tactic/sls/sls_engine.h   | 3 +--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 9fa2cc263..cc06e4f78 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -868,6 +868,7 @@ bailout:
     return res;
 }
 
+#if 0 // Old code.
 // main search loop
 lbool sls_engine::search_old() {
     lbool res = l_undef;
@@ -1060,6 +1061,7 @@ lbool sls_engine::search_old() {
             }
         }
     }
+#endif
 
 bailout:
     m_mpz_manager.del(new_value);
@@ -1190,4 +1192,4 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         return 0;
     }
     return 1;
-}
\ No newline at end of file
+}
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8458817b6..5d4c9a0fc 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -114,7 +114,6 @@ public:
 
 protected:
     void checkpoint();
-    lbool search_old(void);
     double get_restart_armin(unsigned cnt_restarts);    
 
     bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
@@ -148,4 +147,4 @@ protected:
     inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
\ No newline at end of file
+#endif

From c5e059211f5e1c919ab21714520d4f2434a50c07 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 27 Mar 2014 13:37:04 +0000
Subject: [PATCH 011/108] bugfix

---
 src/tactic/sls/sls_engine.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index cc06e4f78..10aaf6601 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1061,13 +1061,13 @@ lbool sls_engine::search_old() {
             }
         }
     }
-#endif
 
 bailout:
     m_mpz_manager.del(new_value);
 
     return res;
 }
+#endif
 
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {

From 883762d54a7352997bb496a0d75e29d48df851f7 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:27:06 +0000
Subject: [PATCH 012/108] removed dependency of bvsls on goal_refs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 1b451e8fd..e29cebe90 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -276,13 +276,13 @@ public:
     }
 #endif
 
-    void uct_forget(goal_ref const & g) {
+    void uct_forget(ptr_vector<expr> & as) {
         expr * e;
         unsigned touched_old, touched_new;
 
-        for (unsigned i = 0; i < g->size(); i++)
+        for (unsigned i = 0; i < as.size(); i++)
         {
-            e = g->form(i);
+            e = as[i];
             touched_old = m_scores.find(e).touched;
             touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
             m_scores.find(e).touched = touched_new;

From 176715aea07ed98b4fedf188cf2e1af1a3e4f624 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:28:40 +0000
Subject: [PATCH 013/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index e29cebe90..f5c77fc35 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,6 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
+#include"for_each_expr.h"
 #include"bv_decl_plugin.h"
 #include"model.h"
 

From 8e5659ac4cf795ba2f375515cbb2a5c0874ec0c0 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:30:15 +0000
Subject: [PATCH 014/108] compilation fixes

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.h  | 1 +
 src/tactic/sls/sls_tracker.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 5d4c9a0fc..96041d09e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,6 +22,7 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
+#include"goal.h"
 
 #include"sls_compilation_settings.h"
 #include"sls_tracker.h"
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index f5c77fc35..50d0e4188 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -21,6 +21,7 @@ Notes:
 #define _SLS_TRACKER_H_
 
 #include"for_each_expr.h"
+#include"ast_smt2_pp.h"
 #include"bv_decl_plugin.h"
 #include"model.h"
 

From 24d662ba49a487517758e6e2e7489ffdf47075fb Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 14:58:59 +0000
Subject: [PATCH 015/108] bvsls refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 21 ++++++++++++---------
 src/tactic/sls/sls_engine.h   |  2 ++
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 10aaf6601..e7ee2abbd 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1069,6 +1069,16 @@ bailout:
 }
 #endif
 
+void sls_engine::init_tracker() {
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(m_assertions);
+}
+
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {
         mc = 0;
@@ -1078,8 +1088,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     m_produce_models = g->models_enabled();
 
     for (unsigned i = 0; i < g->size(); i++)
-        assert_expr(g->form(i));
-    
+        assert_expr(g->form(i));    
 
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
@@ -1118,13 +1127,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
     verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-#if _WEIGHT_DIST_ == 4
-    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-    m_tracker.initialize(m_assertions);
+    init_tracker();
     lbool res = l_undef;
 
     m_restart_limit = _RESTART_LIMIT_;
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 96041d09e..c56d6ec40 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -109,6 +109,8 @@ public:
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
     void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
+    void init_tracker(void);
+
     lbool search(void);    
 
     void operator()(goal_ref const & g, model_converter_ref & mc);

From 0f5d2e010dd207b99c20696bef8eb0945d569be5 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 15:26:52 +0000
Subject: [PATCH 016/108] bvsls refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 44 +++++++++++++++++++----------------
 src/tactic/sls/sls_engine.h   |  1 +
 2 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index e7ee2abbd..2b359608a 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1125,8 +1125,31 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
     verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;    
 
+    lbool res = operator()();
+
+    if (res == l_true) {
+        report_tactic_progress("Number of flips:", m_stats.m_moves);
+        for (unsigned i = 0; i < g->size(); i++)
+            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+            {
+                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                NOT_IMPLEMENTED_YET();
+            }
+
+        if (m_produce_models) {
+            model_ref mdl = m_tracker.get_model();
+            mc = model2model_converter(mdl.get());
+            TRACE("sls_model", mc->display(tout););
+        }
+        g->reset();
+    }
+    else
+        mc = 0;
+}
+
+lbool sls_engine::operator()() {
     init_tracker();
     lbool res = l_undef;
 
@@ -1149,25 +1172,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
 
     verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-    if (res == l_true) {
-        report_tactic_progress("Number of flips:", m_stats.m_moves);
-        for (unsigned i = 0; i < g->size(); i++)
-            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-            {
-                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                NOT_IMPLEMENTED_YET();
-            }
-
-        if (m_produce_models) {
-            model_ref mdl = m_tracker.get_model();
-            mc = model2model_converter(mdl.get());
-            TRACE("sls_model", mc->display(tout););
-        }
-        g->reset();
-    }
-    else
-        mc = 0;
 }
 
 unsigned sls_engine::check_restart(unsigned curr_value)
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index c56d6ec40..c6e3af155 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -113,6 +113,7 @@ public:
 
     lbool search(void);    
 
+    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:

From f8ee58b30122b53e5cd2fb9c346788c2c732f0f0 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 15:28:02 +0000
Subject: [PATCH 017/108] bvsls bugfix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 2b359608a..dc4451bb5 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1172,6 +1172,8 @@ lbool sls_engine::operator()() {
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
 
     verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+    
+    return res;
 }
 
 unsigned sls_engine::check_restart(unsigned curr_value)

From ef1d8f2acc9aca562a83e55f89e8820b48c525d5 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Sun, 20 Apr 2014 16:38:49 +0100
Subject: [PATCH 018/108] Current version before integration ...

---
 src/tactic/sls/sls_compilation_settings.h |  36 +-
 src/tactic/sls/sls_engine.cpp             | 348 ++++++++++++++++++--
 src/tactic/sls/sls_engine.h               |  12 +-
 src/tactic/sls/sls_evaluator.h            | 146 ++++++++-
 src/tactic/sls/sls_tactic.cpp             |   4 +-
 src/tactic/sls/sls_tracker.h              | 379 +++++++++++++++++++++-
 src/tactic/smtlogics/qfbv_tactic.cpp      |  28 ++
 7 files changed, 885 insertions(+), 68 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 4d8c83599..d2b899dd8 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -36,17 +36,21 @@ Notes:
 // do we use dirty unit propagation to get rid of nested top level assertions?
 #define _DIRTY_UP_ 0
 
+// shall we use additive weighting scheme?
+#define _PAWS_ 5
+#define _PAWS_INIT_ 40
+
 // do we use restarts?
 // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
+#define _RESTARTS_ 1
 // limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
+#define _RESTART_LIMIT_ 100
 // 0 = initialize with all zero, 1 initialize with random value
 #define _RESTART_INIT_ 0
 // 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
 #define _RESTART_SCHEME_ 1
 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 3.0
+#define _RESTART_CONST_ARMIN_ 2.0
 
 // timelimit
 #define _TIMELIMIT_ 3600
@@ -61,6 +65,21 @@ Notes:
 // 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
 #define _VNS_ 0
 
+// shall we check 2-bit flips in plateaus using Monte Carlo?
+#define _VNS_MC_ 0
+
+// how many 2-bit flips shall we try per bit?
+#define _VNS_MC_TRIES_ 1
+
+// shall we check another assertion if no improving step was found in the first one?
+#define _VNS_REPICK_ 0
+
+// what is the probability of doing so (percentage)?
+#define _VNS_PERC_ 100
+
+// do a decreasing move with percentage ...
+#define _INSIST_PERC_ 0
+
 // do we reduce the score of unsatisfied literals?
 // 0 = no
 // 1 = yes, by multiplying it with some factor
@@ -70,7 +89,7 @@ Notes:
 #define _WEIGHT_DIST_ 1
 
 // the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.25
+#define _WEIGHT_DIST_FACTOR_ 0.5
 
 // shall we toggle the weight after each restart?
 #define _WEIGHT_TOGGLE_ 0
@@ -82,14 +101,15 @@ Notes:
 // what is the percentage of random moves in plateaus (instead of full randomization)?
 #define _PERC_PLATEAU_MOVES_ 0
 
-// shall we repick clause when randomizing in a plateau or use the current one?
+// shall we repick assertion when randomizing in a plateau or use the current one?
+// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one
 #define _REPICK_ 1
 
 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_
 #define _UCT_ 1
 
 // how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 10.0
+#define _UCT_CONSTANT_ 20.0
 
 // is uct clause selection probabilistic similar to variable selection in sparrow?
 // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
@@ -103,11 +123,11 @@ Notes:
 
 // how shall we initialize the _UCT_ total touched counter?
 // 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 1
+#define _UCT_INIT_ 0
 
 // do we gradually reduce the touched values of _UCT_?
 #define _UCT_FORGET_ 0
-#define _UCT_FORGET_FACTOR_ 0.5
+#define _UCT_FORGET_FACTOR_ 0.9
 
 // shall we use addition/subtraction?
 #define _USE_ADDSUB_ 1
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 92471aad8..342e649af 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -169,6 +169,14 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c
 #endif
 }
 
+double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+    m_stats.m_incr_evals++;
+    if (m_evaluator.update_prune_new(fd, new_value))
+        return (m_tracker.get_top_sum() / g->size());
+    else
+        return 0.0;
+}
+
 // checks whether the score outcome of a given move is better than the previous score
 bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                 double & best_score, unsigned & best_const, mpz & best_value) {
@@ -190,8 +198,33 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
     m_mpz_manager.del(old_value);
 #endif
 
-    //            if (r >= best_score) {
+    //if (r >= best_score) {
     if (r > best_score) {
+        m_tracker.reset_equal_scores();
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+    /*else if (r == best_score) {
+        if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0)
+        {
+            best_score = r;
+            best_const = fd_inx;
+            m_mpz_manager.set(best_value, temp);
+            return true;
+        }
+    }*/
+
+    return false;
+}
+
+bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
+
+    double r = incremental_score_prune_new(g, fd, temp);
+
+    if (r >= best_score) {
         best_score = r;
         best_const = fd_inx;
         m_mpz_manager.set(best_value, temp);
@@ -426,39 +459,25 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
     return new_score;
 }
 
-// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
     mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-    mpz temp2;
-#endif
-    unsigned bv_sz;
+    unsigned bv_sz, max_bv_sz = 0;
     double new_score = score;
 
-    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
         m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
-        // first try to flip every bit
-#if _SKIP_BITS_
-        for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
-#else
-        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-#endif
-            // What would happen if we flipped bit #i ?                
-            mk_flip(srt, old_value, j, temp);
-
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                new_bit = j;
-                move = MV_FLIP;
-            }
-        }
-
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
@@ -471,9 +490,121 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
                 if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
+
+            // try to flip lsb
+            mk_flip(srt, old_value, 0, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = 0;
+                move = MV_FLIP;
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        SASSERT(check == score);
+    }
+
+    for (unsigned j = 1; j < max_bv_sz; j++)
+    {
+        for (unsigned i = 0; i < to_evaluate.size(); i++) {
+            func_decl * fd = to_evaluate[i];
+            sort * srt = fd->get_range();
+            bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+            // What would happen if we flipped bit #j ?                
+            if (j < bv_sz)
+            {
+                mk_flip(srt, old_value, j, temp);
+
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                    new_bit = j;
+                    move = MV_FLIP;
+                }
+            }
+            // reset to what it was before
+            double check = incremental_score(g, fd, old_value);
+            SASSERT(check == score);
+        }
+    }
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
+// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+    mpz temp2;
+#endif
+    unsigned bv_sz;
+#if _INSIST_PERC_
+    double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score;
+#else
+    double new_score = score;
+#endif
+
+    m_tracker.reset_equal_scores();
+
+//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+//    for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) {
+//    for (unsigned i = to_evaluate.size(); i-- > 0; ) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        // first try to flip every bit
+#if _SKIP_BITS_
+        for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
+#else
+//        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+        for (unsigned j = 0; j < bv_sz; j++) {
+//        for (unsigned j = bv_sz; j-- > 0; ) {
+#endif
+            // What would happen if we flipped bit #i ?                
+            mk_flip(srt, old_value, j, temp);
+
+            //if (m_tracker.get_random_uint(1))
+            //if ((move != MV_FLIP) || (new_bit > j))
+            //{
+            //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) {
+            //    new_bit = j;
+            //    move = MV_FLIP;
+            //}
+            //}
+            //else
+            //{
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = j;
+                move = MV_FLIP;
+            }
+            //}
+        }
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+#if _USE_ADDSUB_
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                //if (m_tracker.get_random_uint(1))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                //if (m_tracker.get_random_uint(1))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
+            //if (m_tracker.get_random_uint(1))
             if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
@@ -514,6 +645,50 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
 #if _USE_MUL3_
     m_mpz_manager.del(temp2);
 #endif
+
+    if ((new_score == score) && 1)// (m_tracker.get_random_uint(1)))
+        best_const = -1;
+
+    return new_score;
+}
+
+// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value) {
+    mpz old_value, temp, temp2;
+    unsigned bv_sz;
+    double new_score = score;
+
+//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) {
+//            for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+            for (unsigned j = 0; j < bv_sz; j++) {
+                mk_flip(srt, old_value, j, temp);
+                for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++)
+                {
+                    unsigned k = m_tracker.get_random_uint(16) % bv_sz;
+                    while (k == j)
+                        k = m_tracker.get_random_uint(16) % bv_sz;
+                    mk_flip(srt, temp, k, temp2);
+                    what_if(g, fd, i, temp2, new_score, best_const, best_value);
+                }
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(temp2);
+
     return new_score;
 }
 
@@ -725,6 +900,13 @@ lbool sls_engine::search(goal_ref const & g) {
 
     score = rescore(g);
     unsigned sz = g->size();
+
+    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+    tout << "Score distribution:";
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    tout << " TOP: " << score << std::endl;);
+
 #if _PERC_STICKY_
     expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
@@ -738,9 +920,18 @@ lbool sls_engine::search(goal_ref const & g) {
 #else
     while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
 #endif
+        //if (m_stats.m_stopwatch.get_current_seconds() > 10.0)
+        //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);}
+
         checkpoint();
         m_stats.m_moves++;
 
+#if _UCT_FORGET_
+        //if (m_stats.m_moves % sz == 0)
+        if (m_stats.m_moves % _UCT_FORGET_ == 0)
+            m_tracker.uct_forget(g);
+#endif
+
 #if _REAL_RS_ || _REAL_PBFS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
@@ -757,6 +948,7 @@ lbool sls_engine::search(goal_ref const & g) {
             res = l_true;
             goto bailout;
         }
+        //ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_only(e);
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
 #else
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
@@ -789,6 +981,8 @@ lbool sls_engine::search(goal_ref const & g) {
 #endif       
         old_score = score;
         new_const = (unsigned)-1;
+        move = MV_FLIP;
+        new_bit = 0;
 
 #if _VNS_
         score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
@@ -796,6 +990,60 @@ lbool sls_engine::search(goal_ref const & g) {
         score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
 
+#if _VNS_MC_ > _VNS_REPICK_
+#if _VNS_MC_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+#endif
+#if _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+#endif
+#endif
+
+#if _VNS_MC_ < _VNS_REPICK_
+#if _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+#endif
+#if _VNS_MC_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+#endif
+#endif
+
+#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1)) {
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+            else {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+        }        
+#endif
+
+
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
             plateau_cnt++;
@@ -810,10 +1058,19 @@ lbool sls_engine::search(goal_ref const & g) {
                 mk_random_move(to_evaluate);
             else
 #endif
-#if _REPICK_
+#if _REPICK_ == 1
                 m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _REPICK_ == 2
+            {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                    m_evaluator.randomize_local(q);
+                else
+                    m_evaluator.randomize_local(e);
+            }
 #else
-                m_evaluator.randomize_local(to_evaluate);
+                m_evaluator.randomize_local_n(g, to_evaluate);
+                //m_evaluator.randomize_local(to_evaluate);
 #endif
 #endif
 
@@ -822,10 +1079,28 @@ lbool sls_engine::search(goal_ref const & g) {
 #else
             score = top_score(g);
 #endif
+
+#if _PAWS_
+            for (unsigned i = 0; i < sz; i++)
+            {
+                expr * q = g->form(i);
+                if (m_tracker.get_random_uint(16) % 100 < _PAWS_)
+                {
+                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
+                        m_tracker.decrease_weight(q);
+                }
+                else
+                {
+                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
+                        m_tracker.increase_weight(q);
+                }
+            }
+#endif
+
         }
         else {
             func_decl * fd = to_evaluate[new_const];
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
             score = serious_score(g, fd, new_value);
 #else
             score = incremental_score(g, fd, new_value);
@@ -961,7 +1236,7 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 case MV_DIV2: m_stats.m_div2s++; break;
                 }
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
                 score = serious_score(g, fd, new_value);
 #else
                 score = incremental_score(g, fd, new_value);
@@ -1056,7 +1331,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
     verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
     verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+    verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl;
+    verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl;
     verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+    verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl;
+    verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl;
+    verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl;
+    verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl;
+    verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl;
     verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
     verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
     verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
@@ -1067,6 +1349,8 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
     verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
     verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+    verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
+    verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
     verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
     verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
     verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
@@ -1136,7 +1420,9 @@ unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_limit)
     {
-#if _RESTART_SCHEME_ == 4
+#if _RESTART_SCHEME_ == 5
+        m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+#elif _RESTART_SCHEME_ == 4
         m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
         m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
@@ -1144,9 +1430,11 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
 #elif _RESTART_SCHEME_ == 1
         if (m_stats.m_restarts & 1)
+        //if (m_stats.m_restarts % 3 == 2)
             m_restart_limit += _RESTART_LIMIT_;
         else
             m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+            //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_;
 #else
         m_restart_limit += _RESTART_LIMIT_;
 #endif
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 878354c6d..902c6b7a0 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -108,7 +108,13 @@ public:
 
     double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
                           unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
+
+    double find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+
+    double find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value);
+
     double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
                                 unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
     
@@ -132,6 +138,10 @@ protected:
     bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
 
+    bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                 double & best_score, unsigned & best_const, mpz & best_value);
+    double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value);
+
     bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                        double & best_score, unsigned & best_const, mpz & best_value);
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 8d2a7ba1d..78f2cb79a 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -575,7 +575,7 @@ public:
 #if _CACHE_TOP_SCORE_
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
@@ -584,12 +584,13 @@ public:
                 new_score = m_tracker.score(cur);
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
 #endif            
+
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -634,7 +635,7 @@ public:
 #if _CACHE_TOP_SCORE_
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
@@ -643,7 +644,7 @@ public:
                 new_score = m_tracker.score(cur);
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
@@ -683,7 +684,7 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         run_serious_update(max_depth);
 #else
         run_update(max_depth);
@@ -729,14 +730,16 @@ public:
 #if _CACHE_TOP_SCORE_
             //if (!m_tracker.has_uplinks(cur))
             if (m_tracker.is_top_expr(cur))
-                m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
             prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
             if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+            //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
                 pot_benefits = 1;
             if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+            //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
                 pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
@@ -771,7 +774,7 @@ public:
                     new_score = m_tracker.score(cur); 
                     //if (!m_tracker.has_uplinks(cur))
                     if (m_tracker.is_top_expr(cur))
-                        m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
 #else
                     m_tracker.set_score(cur, m_tracker.score(cur));
@@ -858,6 +861,104 @@ public:
     }
 #endif
 
+    unsigned run_update_bool_prune_new(unsigned cur_depth) {
+        expr_fast_mark1 visited;
+
+        double prune_score, new_score;
+        unsigned pot_benefits = 0;
+        SASSERT(cur_depth < m_traversal_stack_bool.size());
+ 
+        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+
+        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+            expr * cur = cur_depth_exprs[i];
+
+            new_score = m_tracker.score(cur); 
+            //if (!m_tracker.has_uplinks(cur))
+            if (m_tracker.is_top_expr(cur))
+                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+            prune_score = m_tracker.get_score_prune(cur);
+            m_tracker.set_score(cur, new_score);
+
+            if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
+                pot_benefits = 1;
+            if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
+                pot_benefits = 1;
+
+            if (m_tracker.has_uplinks(cur)) {
+                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                for (unsigned j = 0; j < ups.size(); j++) {
+                    expr * next = ups[j];
+                    unsigned next_d = m_tracker.get_distance(next);
+                    SASSERT(next_d < cur_depth);
+                    if (!visited.is_marked(next)) {
+                        m_traversal_stack_bool[next_d].push_back(next);
+                        visited.mark(next);
+                    }
+                }
+            }
+            else
+            {
+            }
+        }
+
+        cur_depth_exprs.reset();
+        cur_depth--;
+ 
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+            if (pot_benefits)
+            {
+                unsigned cur_size = cur_depth_exprs.size();
+                for (unsigned i = 0; i < cur_size; i++) {
+                    expr * cur = cur_depth_exprs[i];
+
+                    new_score = m_tracker.score(cur); 
+                    //if (!m_tracker.has_uplinks(cur))
+                    if (m_tracker.is_top_expr(cur))
+                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                    m_tracker.set_score(cur, new_score);
+                    if (m_tracker.has_uplinks(cur)) {
+                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                        for (unsigned j = 0; j < ups.size(); j++) {
+                            expr * next = ups[j];
+                            unsigned next_d = m_tracker.get_distance(next);
+                            SASSERT(next_d < cur_depth);
+                            if (!visited.is_marked(next)) {
+                                m_traversal_stack_bool[next_d].push_back(next);
+                                visited.mark(next);
+                            }
+                        }
+                    }
+                }
+            }
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        return pot_benefits;
+    }
+
+    unsigned update_prune_new(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+
+        if (m_traversal_stack_bool.size() <= cur_depth)
+            m_traversal_stack_bool.resize(cur_depth+1);
+        if (m_traversal_stack.size() <= cur_depth) 
+                m_traversal_stack.resize(cur_depth+1);
+
+        if (m_manager.is_bool(ep))
+            m_traversal_stack_bool[cur_depth].push_back(ep);
+        else
+        {
+            m_traversal_stack[cur_depth].push_back(ep);
+            run_update_prune(cur_depth);
+        }
+        return run_update_bool_prune_new(cur_depth);
+    }
+
     void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _all_ candidates:
 
@@ -901,7 +1002,7 @@ public:
         mpz temp = m_tracker.get_random(fd->get_range());
 #endif
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         serious_update(fd, temp);
 #else
         update(fd, temp);
@@ -922,9 +1023,36 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-     void randomize_local(goal_ref const & g, unsigned int flip) {
+    void randomize_local(goal_ref const & g, unsigned int flip) {
         randomize_local(m_tracker.get_unsat_constants(g, flip));
     } 
+
+    void randomize_local_n(goal_ref const & g, ptr_vector<func_decl> & unsat_constants) {
+        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
+        func_decl * fd = unsat_constants[r];
+        sort * srt = fd->get_range();
+        unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); 
+        mpz max_val = m_tracker.get_random(srt);
+        update(fd, max_val);
+        double max_score = m_tracker.get_top_sum() / g->size();
+        mpz temp_val;
+        double temp_score;
+        for (unsigned i = 1; i < 2; i++)
+        //for (unsigned i = 1; i < bv_sz; i++)
+        {
+            m_mpz_manager.set(temp_val, m_tracker.get_random(srt));
+            update(fd, temp_val);
+            temp_score = m_tracker.get_top_sum() / g->size();
+            if (temp_score > max_score)
+            {
+                m_mpz_manager.set(max_val, temp_val);
+                max_score = temp_score;
+            }
+        }
+        update(fd, max_val);
+        m_mpz_manager.del(temp_val);
+        m_mpz_manager.del(max_val);
+    }
 };
 
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index a9b110224..7a9252fe2 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -161,14 +161,14 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                         mk_max_bv_sharing_tactic(m),
                         // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
                         //mk_ctx_simplify_tactic(m, ctx_p),
-                        // Andreas: This one at least eliminates top level duplicates ...
+                        // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance!
                         //mk_simplify_tactic(m),
-                        // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
     tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
+//    tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 6ac054246..87c90f1f8 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -86,12 +86,17 @@ private:
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
 #endif
+#if _PAWS_
+    obj_map<expr, unsigned> m_weights;
+    //obj_map<expr, double> m_weights;
+#endif
 #if _CACHE_TOP_SCORE_
     double				  m_top_sum;
 #endif
 #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     double				  m_weight_dist_factor;
 #endif
+    unsigned              m_equal_scores;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -111,15 +116,52 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+    unsigned get_formula_size() {
+        return m_scores.size();
+    }
+
+    double get_avg_bw(goal_ref const & g) {
+        double sum = 0.0;
+        unsigned count = 0;
+
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            m_temp_constants.reset();
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(g->form(i));
+            unsigned sz = this_decls.size();
+            for (unsigned i = 0; i < sz; i++) {
+                func_decl * fd = this_decls[i];
+                m_temp_constants.push_back(fd);
+                sort * srt = fd->get_range();
+                sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);         
+                count++;
+            }
+        }
+
+        return sum / count;   
+    }
+
 #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     inline void set_weight_dist_factor(double val) {
         m_weight_dist_factor = val;
     }
 #endif
 
+    void reset_equal_scores() {
+        m_equal_scores = 1;
+    }
+
+    unsigned inc_equal_scores() {
+        return ++m_equal_scores;
+    }
+
 #if _CACHE_TOP_SCORE_
-    inline void adapt_top_sum(double add, double sub) {
+    inline void adapt_top_sum(expr * e, double add, double sub) {
+#if _PAWS_
+        m_top_sum += m_weights.find(e) * (add - sub);
+#else
         m_top_sum += add - sub;
+#endif
     }
 
     inline void set_top_sum(double new_score) {
@@ -276,6 +318,7 @@ public:
     }
 #endif
 
+#if _UCT_
     void uct_forget(goal_ref const & g) {
         expr * e;
         unsigned touched_old, touched_new;
@@ -289,6 +332,7 @@ public:
             m_touched += touched_new - touched_old;
         }
     }
+#endif
 
     void initialize(app * n) {
         // Build score table
@@ -463,6 +507,15 @@ public:
         //}
 #endif
 
+#if _PAWS_
+        for (unsigned i = 0; i < sz; i++)
+        {
+            expr * e = g->form(i);
+        	if (!m_weights.contains(e))
+        		m_weights.insert(e, _PAWS_INIT_);
+        }
+#endif
+
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
             setup_occs(g->form(i));
@@ -473,6 +526,30 @@ public:
 #endif
     }
 
+#if _PAWS_
+    void increase_weight(expr * e)
+    {
+        //printf("Increasing %d to", m_weights.find(e));
+        m_weights.find(e)++;
+        //m_weights.find(e) *= 1.1;
+        //printf(" %d\n", m_weights.find(e));
+    }
+
+    void decrease_weight(expr * e)
+    {
+        unsigned old_weight = m_weights.find(e);
+        m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_;
+        //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1;
+        //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e));
+    }
+
+    unsigned get_weight(expr * e)
+    //double get_weight(expr * e)
+    {
+        return m_weights.find(e);
+    }
+#endif
+
 #if _REAL_RS_ || _REAL_PBFS_
     void make_assertion(expr * e)
     {
@@ -763,6 +840,7 @@ public:
             const mpz & v1 = get_value(arg1);
             
             if (negated) {                    
+                //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0;
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << std::endl; );
@@ -809,40 +887,209 @@ public:
             SASSERT(a->get_num_args() == 2);
             const mpz & x = get_value(a->get_arg(0));
             const mpz & y = get_value(a->get_arg(1));
-            unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
+            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
 
             if (negated) {
                 if (m_mpz_manager.gt(x, y))
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(x, y, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+/*                  mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_gt = 0;
+                    unsigned curr_gt = 0;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 1;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 0;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
+                    m_mpz_manager.del(x_copy);
+                    m_mpz_manager.del(y_copy);*/
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);                            
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));                            
+                    double dbl = 1.0 - n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    m_mpz_manager.del(diff);
+#endif
+                }
+            }
+            else {
+                if (m_mpz_manager.le(x, y))                        
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(y, x, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-                }
-            }
-            else {
-                if (m_mpz_manager.le(x, y))                        
+                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+/*                  mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_le = 1;
+                    unsigned curr_le = 1;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 0;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 1;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));
-                    double dbl = n.get_double();
+                    double dbl = 1.0 - n.get_double();
                     res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
             }
             TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                     m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
         }
-        else if (m_bv_util.is_bv_sle(n)) { // x <= y
+/*        else if (m_bv_util.is_bv_sle(n)) { // x <= y
+            app * a = to_app(n);
+            SASSERT(a->get_num_args() == 2);
+            const mpz & x = get_value(a->get_arg(0));
+            const mpz & y = get_value(a->get_arg(1));
+            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
+
+            mpz x_unsigned;
+            mpz y_unsigned;
+            const mpz & p = m_powers(bv_sz);
+            const mpz & p_half = m_powers(bv_sz-1);
+            if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } 
+            if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); }                 
+
+            if (negated) {
+                if (x_unsigned > y_unsigned)
+                    res = 1.0; 
+                else {
+                    mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_gt = 0;
+                    unsigned curr_gt = 0;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 1;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 0;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
+                    m_mpz_manager.del(x_copy);
+                    m_mpz_manager.del(y_copy);
+                }
+            }
+            else {
+                if (x_unsigned <= y_unsigned)                        
+                    res = 1.0; 
+                else {
+                    mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_le = 1;
+                    unsigned curr_le = 1;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 0;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 1;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);
+                }
+            }
+            TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
+                                    m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
+
+            m_mpz_manager.del(x_unsigned);
+            m_mpz_manager.del(y_unsigned);
+        }*/
+      else if (m_bv_util.is_bv_sle(n)) { // x <= y
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 2);
             mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0)));
@@ -855,31 +1102,61 @@ public:
 
             if (negated) {
                 if (x > y)
-                    res = 1.0;
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(x, y, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
+                    res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);
                     rational n(diff);
                     n /= p;
-                    double dbl = n.get_double();
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    double dbl = 1.0 - n.get_double();
+                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
             else {
                 if (x <= y)
-                    res = 1.0;
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(y, x, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
+                    res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
+                    SASSERT(!m_mpz_manager.is_neg(diff));
                     rational n(diff);
                     n /= p;
-                    double dbl = n.get_double();
+                    double dbl = 1.0 - n.get_double();
                     res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
@@ -1149,12 +1426,58 @@ public:
         return go_deeper(q);
     }
 
+    void go_deeper_only(expr * e) {
+            //if (m_manager.is_bool(e)) {
+                if (m_manager.is_and(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    unsigned cnt_unsat = 0, pos = -1;
+                    for (unsigned int i = 0; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+                        //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q);
+                    }
+                    go_deeper(args[pos]);
+                }
+                else if (m_manager.is_or(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    for (unsigned int i = 0; i < sz; i++) {
+                        expr * q = args[i];
+                        go_deeper(q);
+                    }
+                }
+            //}
+                else
+                {
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+                }
+    }
+
+    ptr_vector<func_decl> & get_unsat_constants_only(expr * e) {
+            if (e && !m_temp_constants.size())
+                go_deeper_only(e);
+
+            return m_temp_constants;
+    }
+
     ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
             if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            {
+                m_temp_constants.reset();
                 return m_temp_constants;
+            }
             else
                 return get_constants();
         }
@@ -1303,12 +1626,15 @@ public:
         }
     }
     
-
     expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
-        if (sz == 1)
-            return g->form(0);
+        if (sz == 1) {
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_zero))
+                return g->form(0);
+            else
+                return 0;
+        }
 
         m_temp_constants.reset();
 #if _FOCUS_ == 1
@@ -1357,7 +1683,7 @@ public:
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #elif _UCT_ == 3
@@ -1440,6 +1766,23 @@ public:
         return get_unsat_constants_crsat(g, sz, pos);
 #endif
     }
+
+    expr * get_new_unsat_assertion(goal_ref const & g, expr * e) {
+        unsigned sz = g->size();
+
+        if (sz == 1)
+            return 0;
+
+        m_temp_constants.reset();
+
+        unsigned cnt_unsat = 0, pos = -1;
+        for (unsigned i = 0; i < sz; i++)
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i;	
+
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+    }
 };
 
 #endif
\ No newline at end of file
diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp
index ac53ca0c8..a7870176d 100644
--- a/src/tactic/smtlogics/qfbv_tactic.cpp
+++ b/src/tactic/smtlogics/qfbv_tactic.cpp
@@ -28,6 +28,8 @@ Notes:
 #include"bv_size_reduction_tactic.h"
 #include"aig_tactic.h"
 #include"sat_tactic.h"
+//#include"nnf_tactic.h"
+//#include"sls_tactic.h"
 
 #define MEMLIMIT 300
 
@@ -93,6 +95,32 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) {
                             mk_sat_tactic(m));
 #endif    
     
+    /* use full sls
+    tactic * st = using_params(and_then(preamble_st,
+                                        cond(mk_is_qfbv_probe(),
+                                             cond(mk_is_qfbv_eq_probe(),
+                                                  and_then(mk_bv1_blaster_tactic(m),
+                                                           using_params(mk_smt_tactic(), solver_p)),
+                                                  and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))),
+                                             mk_smt_tactic())),
+                               main_p);*/
+
+    /* use pure dpll
+    tactic * st = using_params(and_then(mk_simplify_tactic(m),
+                                        cond(mk_is_qfbv_probe(),
+                                                  and_then(mk_bit_blaster_tactic(m),
+                                                           when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)),
+                                                                and_then(using_params(and_then(mk_simplify_tactic(m),
+                                                                                               mk_solve_eqs_tactic(m)),
+                                                                                      local_ctx_p),
+                                                                         if_no_proofs(cond(mk_produce_unsat_cores_probe(),
+                                                                                           mk_aig_tactic(),
+                                                                                           using_params(mk_aig_tactic(),
+                                                                                                        big_aig_p))))),
+                                                           new_sat),
+                                             mk_smt_tactic())),
+                               main_p);*/
+
     tactic * st = using_params(and_then(preamble_st,
                                         // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function
                                         // symbols. In this case, we should not use 

From c1741d794155eea8041ef78075aff29b6bbce900 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 00:32:45 +0100
Subject: [PATCH 019/108] Almost cleaned up version.

---
 src/tactic/sls/sls_compilation_settings.h |  72 +------
 src/tactic/sls/sls_engine.cpp             | 231 +++++++---------------
 src/tactic/sls/sls_engine.h               |  13 +-
 src/tactic/sls/sls_evaluator.h            | 175 ++--------------
 src/tactic/sls/sls_tactic.cpp             |   6 +-
 src/tactic/sls/sls_tracker.h              | 170 ++++++++--------
 6 files changed, 177 insertions(+), 490 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 73ba1ffab..9add78daa 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,83 +22,13 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT)
-#define _FOCUS_ 1
-
-// shall we use additive weighting scheme?
-#define _PAWS_ 5
-#define _PAWS_INIT_ 40
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 1
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 100
-//// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 2.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// shall we check 2-bit flips in plateaus using Monte Carlo?
-#define _VNS_MC_ 0
-
-// how many 2-bit flips shall we try per bit?
-#define _VNS_MC_TRIES_ 1
-
-// shall we check another assertion if no improving step was found in the first one?
-#define _VNS_REPICK_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no, 1 = yes, by multiplying it with some factor
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.5
-
-// shall we repick assertion when randomizing in a plateau or use the current one?
-// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 20.0
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 0
-
-// do we gradually reduce the touched values of _UCT_?
-#define _UCT_FORGET_ 0
-#define _UCT_FORGET_FACTOR_ 0.9
-
 // shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
+#define _USE_ADDSUB_ 0
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
 
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
-
 // shall we use early pruning for incremental update?
 #define _EARLY_PRUNE_ 1
 
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-#if ((_UCT_ > 0) + _REAL_RS_ > 1)
-InvalidConfiguration;
-#endif
-
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 938b6e0df..c240a0c51 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -44,6 +44,7 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) :
     m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers)
 {
     updt_params(p);
+    m_tracker.updt_params(p);
 }
 
 sls_engine::~sls_engine() {
@@ -52,19 +53,21 @@ sls_engine::~sls_engine() {
     m_mpz_manager.del(m_two);
 }
 
-double sls_engine::get_restart_armin(unsigned cnt_restarts)
-{
-    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
-}    
-
 void sls_engine::updt_params(params_ref const & _p) {
     sls_params p(_p);
     m_produce_models = _p.get_bool("model", false);
-    m_max_restarts = p.restarts();
+    m_max_restarts = p.max_restarts();
     m_tracker.set_random_seed(p.random_seed());
-    m_plateau_limit = p.plateau_limit();
+    m_walksat = p.walksat();
+    m_walksat_repick = p.walksat_repick();
+    m_paws_sp = p.paws_sp();
+    m_wp = p.wp();
+    m_vns_mc = p.vns_mc();
+    m_vns_repick = p.vns_repick();
+
+    m_restart_base = p.restart_base();
+    m_restart_next = m_restart_base;
+    m_restart_init = p.restart_init();
 }
 
 void sls_engine::checkpoint() {
@@ -105,9 +108,7 @@ double sls_engine::top_score() {
         tout << " " << m_tracker.get_score(m_assertions[i]);
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
-#if _CACHE_TOP_SCORE_
     m_tracker.set_top_sum(top_sum);
-#endif
 
     return top_sum / (double)sz;
 }
@@ -121,37 +122,21 @@ double sls_engine::rescore() {
 double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
     return (m_tracker.get_top_sum() / m_assertions.size());
-#else
-    return top_score();
-#endif
 }
 
 double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
     return (m_tracker.get_top_sum() / m_assertions.size());
-#else
-    return top_score();
-#endif
 }
 
 double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
-#if _EARLY_PRUNE_
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
         return (m_tracker.get_top_sum() / m_assertions.size());
-#else
-        return top_score();
-#endif
     else
         return 0.0;
-#else
-    NOT_IMPLEMENTED_YET();
-#endif
 }
 
 // checks whether the score outcome of a given move is better than the previous score
@@ -261,7 +246,7 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         // inversion doesn't make sense, let's do a flip instead.
         if (mt == MV_INV) mt = MV_FLIP;
 #else
-        mt = MV_FLIP;
+        move_type mt = MV_FLIP;
 #endif
         unsigned bit = 0;
 
@@ -300,7 +285,7 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout););
     }
 
-    m_evaluator.update(fd, new_value);
+    m_evaluator.serious_update(fd, new_value);
     m_mpz_manager.del(new_value);
 }
 
@@ -385,7 +370,7 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) {
             for (unsigned j = 0; j < bv_sz; j++) {
                 mk_flip(srt, old_value, j, temp);
-                for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++)
+                for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++)
                 {
                     unsigned k = m_tracker.get_random_uint(16) % bv_sz;
                     while (k == j)
@@ -411,144 +396,85 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
 lbool sls_engine::search() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
-    unsigned new_const = (unsigned)-1, new_bit = 0;
+    unsigned new_const = (unsigned)-1, new_bit;
     mpz new_value;
     move_type move;
-    unsigned plateau_cnt = 0;
 
     score = rescore();
     unsigned sz = m_assertions.size();
 
-#if _RESTARTS_
-    while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#else
-    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#endif
-
+    while (check_restart(m_stats.m_moves)) {
         checkpoint();
         m_stats.m_moves++;
-
-#if _UCT_FORGET_
-        if (m_stats.m_moves % _UCT_FORGET_ == 0)
-            m_tracker.uct_forget(g);
-#endif
+        if (m_stats.m_moves % m_restart_base == 0)
+            m_tracker.ucb_forget(m_assertions);
 
 #if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
-
-#if _FOCUS_
-        expr * e = m_tracker.get_unsat_assertion(m_assertions);
-
-        if (!e)
-        {
-            res = l_true;
-            goto bailout;
-        }
-        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(m_assertions, sz);
+        
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
         {
             res = l_true;
             goto bailout;
         }
-#endif
 
-        if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+        if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
             mk_random_move(to_evaluate);
-#if _CACHE_TOP_SCORE_
             score = m_tracker.get_top_sum() / sz;
-#else
-            score = top_score(g);
-#endif
             continue;
         }
 
         old_score = score;
         new_const = (unsigned)-1;
-        move = MV_FLIP;
-        new_bit = 0;
 
         score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 
-#if _VNS_MC_ > _VNS_REPICK_
-#if _VNS_MC_
-        if (new_const == static_cast<unsigned>(-1))
-            score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-#endif
-#if _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1))
+        if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
+            score = find_best_move_mc(to_evaluate, score, new_const, new_value);
+   
+        /*if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
         {
-            expr * q = m_tracker.get_new_unsat_assertion(g, e);
+            expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e);
             if (q)
             {
                 ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move);
             }
-        }
-#endif
-#endif
-
-#if _VNS_MC_ < _VNS_REPICK_
-#if _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1))
-        {
-            expr * q = m_tracker.get_new_unsat_assertion(g, e);
-            if (q)
-            {
-                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
-            }
-        }
-#endif
-#if _VNS_MC_
-        if (new_const == static_cast<unsigned>(-1))
-            score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-#endif
-#endif
+        }*/
 
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
-            plateau_cnt++;
-#if _REPICK_
+            if (m_walksat && m_walksat_repick)
                 m_evaluator.randomize_local(m_assertions);
-#else
+            else
                 m_evaluator.randomize_local(to_evaluate);
-#endif
 
-#if _CACHE_TOP_SCORE_
             score = m_tracker.get_top_sum() / m_assertions.size();
-#else
-            score = top_score(g);
-#endif
 
-#if _PAWS_
-            for (unsigned i = 0; i < sz; i++)
+            if (m_paws_sp < 1024)
             {
-                expr * q = m_assertions[i];
-                if (m_tracker.get_random_uint(16) % 100 < _PAWS_)
+                for (unsigned i = 0; i < sz; i++)
                 {
-                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
-                        m_tracker.decrease_weight(q);
-                }
-                else
-                {
-                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
-                        m_tracker.increase_weight(q);
+                    expr * q = m_assertions[i];
+                    if (m_tracker.get_random_uint(10) < m_paws_sp)
+                    {
+                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
+                            m_tracker.decrease_weight(q);
+                    }
+                    else
+                    {
+                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
+                            m_tracker.increase_weight(q);
+                    }
                 }
             }
-#endif
-
         }
         else {
             func_decl * fd = to_evaluate[new_const];
-#if _REAL_RS_ || _PAWS_
             score = serious_score(fd, new_value);
-#else
-            score = incremental_score(fd, new_value);
-#endif
         }
     }
 
@@ -569,30 +495,9 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     for (unsigned i = 0; i < g->size(); i++)
         assert_expr(g->form(i));    
 
-    verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-    verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-    verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-    verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-    verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-    verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-    verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl;
-    verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl;
-    verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl;
-    verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl;
-    verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl;
-    verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-    verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-    verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-    verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-    verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-    verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-    verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
-    verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
     verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-    verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;    
 
     lbool res = operator()();
 
@@ -620,8 +525,6 @@ lbool sls_engine::operator()() {
     m_tracker.initialize(m_assertions);
     lbool res = l_undef;
 
-    m_restart_limit = _RESTART_LIMIT_;
-
     do {
         checkpoint();
 
@@ -630,39 +533,53 @@ lbool sls_engine::operator()() {
 
         if (res == l_undef)
         {
-#if _RESTART_INIT_
-            m_tracker.randomize();
-#else
-            m_tracker.reset(m_assertions);
-#endif
+            if (m_restart_init)
+                m_tracker.randomize(m_assertions);
+            else
+                m_tracker.reset(m_assertions);
         }
-    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+    } while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
 
     verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
     
     return res;
 }
 
-unsigned sls_engine::check_restart(unsigned curr_value)
+/* Andreas: Needed for Armin's restart scheme if we don't want to use loops.
+inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
 {
-    if (curr_value > m_restart_limit)
+    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
+}    
+*/
+
+inline unsigned sls_engine::check_restart(unsigned curr_value)
+{
+    if (curr_value > m_restart_next)
     {
+        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter.
+        I leave the other versions as comments in case you want to try it again somewhen.
 #if _RESTART_SCHEME_ == 5
-        m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+        m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
 #elif _RESTART_SCHEME_ == 4
-        m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+        m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
-        m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+        m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base;
 #elif _RESTART_SCHEME_ == 2
-        m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+        m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base;
 #elif _RESTART_SCHEME_ == 1
         if (m_stats.m_restarts & 1)
-            m_restart_limit += _RESTART_LIMIT_;
+            m_restart_next += m_restart_base;
         else
-            m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
 #else
-        m_restart_limit += _RESTART_LIMIT_;
-#endif
+        m_restart_limit += m_restart_base;
+#endif  */
+        if (m_stats.m_restarts & 1)
+            m_restart_next += m_restart_base;
+        else
+            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
         return 0;
     }
     return 1;
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 4e5af8c93..ff0e55f24 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -70,9 +70,16 @@ protected:
     sls_evaluator   m_evaluator;
     ptr_vector<expr> m_assertions;
 
-    unsigned		m_restart_limit;
     unsigned        m_max_restarts;
-    unsigned        m_plateau_limit;
+    unsigned        m_walksat;
+    unsigned        m_walksat_repick;
+    unsigned        m_wp;
+    unsigned        m_vns_mc;
+    unsigned        m_vns_repick;
+    unsigned        m_paws_sp;
+    unsigned        m_restart_base;
+    unsigned        m_restart_next;
+    unsigned        m_restart_init;
 
     ptr_vector<mpz> m_old_values;
 
@@ -110,7 +117,6 @@ public:
 
 protected:
     void checkpoint();
-    double get_restart_armin(unsigned cnt_restarts);    
 
     bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
@@ -129,6 +135,7 @@ protected:
 
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
 
+    //inline double get_restart_armin(unsigned cnt_restarts);    
     inline unsigned check_restart(unsigned curr_value);
 };
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index da2a4b29f..37bfa5a2d 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -81,11 +81,7 @@ public:
             case OP_AND: {
                 m_mpz_manager.set(result, m_one);
                 for (unsigned i = 0; i < n_args; i++)
-#if _DIRTY_UP_
-                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i]))  {
-#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result))  {
-#endif
                         m_mpz_manager.set(result, m_zero);
                         break;
                     }
@@ -93,11 +89,7 @@ public:
             }
             case OP_OR: {
                 for (unsigned i = 0; i < n_args; i++)
-#if _DIRTY_UP_
-                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i]))  {
-#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) {
-#endif
                         m_mpz_manager.set(result, m_one);
                         break;
                     }
@@ -105,16 +97,9 @@ public:
             }
             case OP_NOT: {
                 SASSERT(n_args == 1);
-#if _DIRTY_UP_
-                if (m_tracker.is_top_expr(args[0]))
-                    m_mpz_manager.set(result, m_zero);
-                else
-                    m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero);
-#else
                 const mpz & child = m_tracker.get_value(args[0]);
                 SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child));                
                 m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);
-#endif
                 break;
             }
             case OP_EQ: {
@@ -545,9 +530,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
         double new_score;
-#endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
@@ -569,23 +552,12 @@ public:
                 }
 #endif
 
+                new_score = m_tracker.score(cur);
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #if _EARLY_PRUNE_
-                new_score = m_tracker.score(cur);
-#if _CACHE_TOP_SCORE_
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
-                m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
-#else
-#if _CACHE_TOP_SCORE_
-                new_score = m_tracker.score(cur);
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                m_tracker.set_score(cur, new_score);
-#else
-                m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
 #endif            
 
                 if (m_tracker.has_uplinks(cur)) {
@@ -614,9 +586,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
         double new_score;
-#endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
@@ -627,23 +597,12 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
+                new_score = m_tracker.score(cur);
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #if _EARLY_PRUNE_
-                new_score = m_tracker.score(cur);
-#if _CACHE_TOP_SCORE_
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
-                m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
-#else
-#if _CACHE_TOP_SCORE_
-                new_score = m_tracker.score(cur);
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                m_tracker.set_score(cur, new_score);
-#else
-                m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
 #endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -679,11 +638,7 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-#if _REAL_RS_ || _PAWS_
         run_serious_update(max_depth);
-#else
-        run_update(max_depth);
-#endif
     }
 
     void update(func_decl * fd, const mpz & new_value) {
@@ -708,7 +663,6 @@ public:
         run_serious_update(cur_depth);
     }
 
-#if _EARLY_PRUNE_
     unsigned run_update_bool_prune(unsigned cur_depth) {
         expr_fast_mark1 visited;
 
@@ -722,10 +676,9 @@ public:
             expr * cur = cur_depth_exprs[i];
 
             new_score = m_tracker.score(cur); 
-#if _CACHE_TOP_SCORE_
             if (m_tracker.is_top_expr(cur))
                 m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
+
             prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
@@ -746,9 +699,6 @@ public:
                     }
                 }
             }
-            else
-            {
-            }
         }
 
         cur_depth_exprs.reset();
@@ -762,14 +712,11 @@ public:
                 for (unsigned i = 0; i < cur_size; i++) {
                     expr * cur = cur_depth_exprs[i];
 
-#if _CACHE_TOP_SCORE_
                     new_score = m_tracker.score(cur); 
                     if (m_tracker.is_top_expr(cur))
                         m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
-#else
-                    m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
+
                     if (m_tracker.has_uplinks(cur)) {
                         ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                         for (unsigned j = 0; j < ups.size(); j++) {
@@ -850,103 +797,6 @@ public:
         }
         return run_update_bool_prune(cur_depth);
     }
-#endif
-
-    unsigned run_update_bool_prune_new(unsigned cur_depth) {
-        expr_fast_mark1 visited;
-
-        double prune_score, new_score;
-        unsigned pot_benefits = 0;
-        SASSERT(cur_depth < m_traversal_stack_bool.size());
- 
-        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-
-        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
-            expr * cur = cur_depth_exprs[i];
-
-            new_score = m_tracker.score(cur); 
-            if (m_tracker.is_top_expr(cur))
-                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-            prune_score = m_tracker.get_score_prune(cur);
-            m_tracker.set_score(cur, new_score);
-
-            if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
-                pot_benefits = 1;
-            if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
-                pot_benefits = 1;
-
-            if (m_tracker.has_uplinks(cur)) {
-                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                for (unsigned j = 0; j < ups.size(); j++) {
-                    expr * next = ups[j];
-                    unsigned next_d = m_tracker.get_distance(next);
-                    SASSERT(next_d < cur_depth);
-                    if (!visited.is_marked(next)) {
-                        m_traversal_stack_bool[next_d].push_back(next);
-                        visited.mark(next);
-                    }
-                }
-            }
-            else
-            {
-            }
-        }
-
-        cur_depth_exprs.reset();
-        cur_depth--;
- 
-        while (cur_depth != static_cast<unsigned>(-1)) {
-            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-            if (pot_benefits)
-            {
-                unsigned cur_size = cur_depth_exprs.size();
-                for (unsigned i = 0; i < cur_size; i++) {
-                    expr * cur = cur_depth_exprs[i];
-
-                    new_score = m_tracker.score(cur); 
-                    if (m_tracker.is_top_expr(cur))
-                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                    m_tracker.set_score(cur, new_score);
-                    if (m_tracker.has_uplinks(cur)) {
-                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                        for (unsigned j = 0; j < ups.size(); j++) {
-                            expr * next = ups[j];
-                            unsigned next_d = m_tracker.get_distance(next);
-                            SASSERT(next_d < cur_depth);
-                            if (!visited.is_marked(next)) {
-                                m_traversal_stack_bool[next_d].push_back(next);
-                                visited.mark(next);
-                            }
-                        }
-                    }
-                }
-            }
-            cur_depth_exprs.reset();
-            cur_depth--;
-        }
-
-        return pot_benefits;
-    }
-
-    unsigned update_prune_new(func_decl * fd, const mpz & new_value) {
-        m_tracker.set_value(fd, new_value);
-        expr * ep = m_tracker.get_entry_point(fd);
-        unsigned cur_depth = m_tracker.get_distance(ep);
-
-        if (m_traversal_stack_bool.size() <= cur_depth)
-            m_traversal_stack_bool.resize(cur_depth+1);
-        if (m_traversal_stack.size() <= cur_depth) 
-                m_traversal_stack.resize(cur_depth+1);
-
-        if (m_manager.is_bool(ep))
-            m_traversal_stack_bool[cur_depth].push_back(ep);
-        else
-        {
-            m_traversal_stack[cur_depth].push_back(ep);
-            run_update_prune(cur_depth);
-        }
-        return run_update_bool_prune_new(cur_depth);
-    }
 
     void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _one_ candidate:
@@ -954,11 +804,8 @@ public:
         func_decl * fd = unsat_constants[r];
         mpz temp = m_tracker.get_random(fd->get_range());
 
-#if _REAL_RS_ || _PAWS_
         serious_update(fd, temp);
-#else
-        update(fd, temp);
-#endif
+
         m_mpz_manager.del(temp);
 
         TRACE("sls",    tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 7a9252fe2..2a40e908d 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -159,16 +159,12 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-                        // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
-                        //mk_ctx_simplify_tactic(m, ctx_p),
-                        // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance!
-                        //mk_simplify_tactic(m),
                         mk_nnf_tactic(m, p));
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
     tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
-//    tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
+    //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 235ab9471..65011dc8d 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -39,11 +39,7 @@ class sls_tracker {
     mpz                   m_zero, m_one, m_two;
         
     struct value_score { 
-#if _EARLY_PRUNE_
         value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
-#else
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
-#endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
@@ -80,20 +76,22 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
-#if _UCT_
+
+    unsigned              m_walksat;
+    unsigned              m_ucb;
+    double                m_ucb_constant;
+    unsigned              m_ucb_init;
+    double                m_ucb_forget;
     unsigned              m_touched;
-#endif
+    double                m_scale_unsat;
+    unsigned              m_paws_init;
 #if _REAL_RS_
     ptr_vector<expr>	  m_unsat_expr;
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
 #endif
-#if _PAWS_
     obj_map<expr, unsigned> m_weights;
-#endif
-#if _CACHE_TOP_SCORE_
     double				  m_top_sum;
-#endif
     unsigned              m_equal_scores;
 
 public:    
@@ -114,6 +112,17 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+    void updt_params(params_ref const & _p) {
+        sls_params p(_p);
+        m_walksat = p.walksat();
+        m_ucb = p.walksat_ucb();
+        m_ucb_constant = p.walksat_ucb_constant();
+        m_ucb_init = p.walksat_ucb_init();
+        m_ucb_forget = p.walksat_ucb_forget();
+        m_scale_unsat = p.scale_unsat();
+        m_paws_init = p.paws_init();
+    }
+
     unsigned get_formula_size() {
         return m_scores.size();
     }
@@ -147,13 +156,8 @@ public:
         return ++m_equal_scores;
     }
 
-#if _CACHE_TOP_SCORE_
     inline void adapt_top_sum(expr * e, double add, double sub) {
-#if _PAWS_
         m_top_sum += m_weights.find(e) * (add - sub);
-#else
-        m_top_sum += add - sub;
-#endif
     }
 
     inline void set_top_sum(double new_score) {
@@ -163,7 +167,6 @@ public:
     inline double get_top_sum() {
         return m_top_sum;
     }
-#endif
 
     inline void set_value(expr * n, const mpz & r) {
         SASSERT(m_scores.contains(n));
@@ -209,7 +212,6 @@ public:
         return get_score(ep);
     }
 
-#if _EARLY_PRUNE_
     inline void set_score_prune(expr * n, double score) {
         SASSERT(m_scores.contains(n));
         m_scores.find(n).score_prune = score;
@@ -229,7 +231,6 @@ public:
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
     }
-#endif
 
     inline unsigned get_distance(expr * n) {
         SASSERT(m_scores.contains(n));
@@ -310,17 +311,20 @@ public:
     }
 #endif
 
-    void uct_forget(ptr_vector<expr> & as) {
-        expr * e;
-        unsigned touched_old, touched_new;
-
-        for (unsigned i = 0; i < as.size(); i++)
+    inline void ucb_forget(ptr_vector<expr> & as) {
+        if (m_ucb_forget < 1.0)
         {
-            e = as[i];
-            touched_old = m_scores.find(e).touched;
-            touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
-            m_scores.find(e).touched = touched_new;
-            m_touched += touched_new - touched_old;
+            expr * e;
+            unsigned touched_old, touched_new;
+
+            for (unsigned i = 0; i < as.size(); i++)
+            {
+                e = as[i];
+                touched_old = m_scores.find(e).touched;
+                touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1);
+                m_scores.find(e).touched = touched_new;
+                m_touched += touched_new - touched_old;
+            }
         }
     }
 
@@ -490,26 +494,21 @@ public:
         //}
 #endif
 
-#if _PAWS_
         for (unsigned i = 0; i < sz; i++)
         {
             expr * e = as[i];
         	if (!m_weights.contains(e))
-        		m_weights.insert(e, _PAWS_INIT_);
+        		m_weights.insert(e, m_paws_init);
         }
-#endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
             setup_occs(as[i]);
 #endif
 
-#if _UCT_
-        m_touched = _UCT_INIT_ ? as.size() : 1;
-#endif
+        m_touched = m_ucb_init ? as.size() : 1;
     }
 
-#if _PAWS_
     void increase_weight(expr * e)
     {
         m_weights.find(e)++;
@@ -518,14 +517,13 @@ public:
     void decrease_weight(expr * e)
     {
         unsigned old_weight = m_weights.find(e);
-        m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_;
+        m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init;
     }
 
     unsigned get_weight(expr * e)
     {
         return m_weights.find(e);
     }
-#endif
 
 #if _REAL_RS_
     void make_assertion(expr * e)
@@ -684,7 +682,6 @@ public:
         }
     }              
 
-#if _EARLY_PRUNE_
     void setup_occs(expr * n, bool negated = false) {
         if (m_manager.is_bool(n))
         {
@@ -717,7 +714,6 @@ public:
         else
             NOT_IMPLEMENTED_YET();
     }
-#endif
 
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
@@ -735,20 +731,17 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            // Andreas: Seems to have no effect. Probably it does not even occur.
-#if _SCORE_AND_AVG_
+            /* Andreas: Seems to have no effect. But maybe you want to try it again at some point.
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
                 sum += get_score(args[i]);
-            res = sum / (double) a->get_num_args();
-#else
+            res = sum / (double) a->get_num_args(); */
             double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur < min) min = cur;
             }
             res = min;
-#endif
         }
         else if (m_manager.is_or(n)) {
             SASSERT(!negated);
@@ -927,13 +920,11 @@ public:
 
         SASSERT(res >= 0.0 && res <= 1.0);
 
-#if _WEIGHT_DIST_
         app * a = to_app(n);
         family_id afid = a->get_family_id();
 
         if (afid == m_bv_util.get_family_id())
-            if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
-#endif
+            if (res < 1.0) res *= m_scale_unsat;
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
@@ -995,8 +986,8 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as, unsigned sz) {
-
+    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as) {
+        unsigned sz = as.size();
         if (sz == 1) {
             if (m_mpz_manager.neq(get_value(as[0]), m_one))
                 return get_constants();
@@ -1033,89 +1024,88 @@ public:
     }
 
     ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as) {
-#if _FOCUS_
-        expr * e = get_unsat_assertion(as);
-
-        if (!e)
+        if (m_walksat)
         {
-            m_temp_constants.reset();
-            return m_temp_constants;
-        }
+            expr * e = get_unsat_assertion(as);
 
-        return get_unsat_constants_walksat(e);
-#else
-        return  m_tracker.get_unsat_constants_gsat(as, sz);
-#endif
+            if (!e)
+            {
+                m_temp_constants.reset();
+                return m_temp_constants;
+            }
+
+            return get_unsat_constants_walksat(e);
+        }
+        else
+            return get_unsat_constants_gsat(as);
     }
     
     expr * get_unsat_assertion(ptr_vector<expr> const & as) {
         unsigned sz = as.size();
-
         if (sz == 1) {
             if (m_mpz_manager.neq(get_value(as[0]), m_one))
                 return as[0];
             else
                 return 0;
         }
-
         m_temp_constants.reset();
-#if _UCT_
+
         unsigned pos = -1;
-        value_score vscore;
-        double max = -1.0;
+        if (m_ucb)
+        {
+            value_score vscore;
+            double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
                 expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
-#if _UCT_ == 1
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
-#elif _UCT_ == 3
+                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+#if _UCT_ == 3
             double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
-            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
+            if (pos == static_cast<unsigned>(-1))
+                return 0;
 
-#if _UCT_
-        m_scores.find(as[pos]).touched++;
-        m_touched++;
-#endif
+            m_scores.find(as[pos]).touched++;
+            m_touched++;
 //        return m_list_false[pos];
+        }
+        else
+        {
+            unsigned cnt_unsat = 0;
+            for (unsigned i = 0; i < sz; i++)
+                if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+            if (pos == static_cast<unsigned>(-1))
+                return 0;
+        }
+        
         return as[pos];
-#elif _REAL_RS_
+#if _REAL_RS_
         //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
         //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
         sz = m_where_false.size();
         if (sz == 0)
             return 0;
         return m_list_false[get_random_uint(16) % sz];
-#else
-        unsigned cnt_unsat = 0, pos = -1;
-        for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
 #endif
-        return as[pos];
     }
 
-    expr * get_new_unsat_assertion(goal_ref const & g, expr * e) {
-        unsigned sz = g->size();
-
+    expr * get_new_unsat_assertion(ptr_vector<expr> const & as, expr * e) {
+        unsigned sz = as.size();
         if (sz == 1)
             return 0;
-
         m_temp_constants.reset();
-
+        
         unsigned cnt_unsat = 0, pos = -1;
         for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i;	
+            if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i;	
 
         if (pos == static_cast<unsigned>(-1))
             return 0;
-        return g->form(pos);
+        return as[pos];
     }
 };
 

From 8346aed39c927923365efa3c2dbabc5bace18cb7 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 01:07:30 +0100
Subject: [PATCH 020/108] Fixed bug with VNS repick.

---
 src/tactic/sls/sls_compilation_settings.h |  2 +-
 src/tactic/sls/sls_engine.cpp             | 22 +++++++++++++++++-----
 src/tactic/sls/sls_tracker.h              |  7 ++++---
 3 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 9add78daa..a649bc9ed 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -23,7 +23,7 @@ Notes:
 #define _SLS_COMPILATION_SETTINGS_H_
 
 // shall we use addition/subtraction?
-#define _USE_ADDSUB_ 0
+#define _USE_ADDSUB_ 1
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index c240a0c51..af8ae1df2 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -68,6 +68,12 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_base = p.restart_base();
     m_restart_next = m_restart_base;
     m_restart_init = p.restart_init();
+
+    // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
+    if (m_walksat_repick && !m_walksat)
+        NOT_IMPLEMENTED_YET();
+    if (m_vns_repick && !m_walksat)
+        NOT_IMPLEMENTED_YET();
 }
 
 void sls_engine::checkpoint() {
@@ -435,19 +441,25 @@ lbool sls_engine::search() {
         if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
             score = find_best_move_mc(to_evaluate, score, new_const, new_value);
    
-        /*if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
+        if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
         {
-            expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e);
+            expr * q = m_tracker.get_new_unsat_assertion(m_assertions);
             if (q)
             {
-                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q);
                 score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move);
+
+                if (new_const != static_cast<unsigned>(-1)) {
+                    func_decl * fd = to_evaluate2[new_const];
+                    score = serious_score(fd, new_value);
+                    continue;
+                }
             }
-        }*/
+        }
 
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
-            if (m_walksat && m_walksat_repick)
+            if (m_walksat_repick)
                 m_evaluator.randomize_local(m_assertions);
             else
                 m_evaluator.randomize_local(to_evaluate);
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 65011dc8d..7b48057d4 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -76,7 +76,7 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
-
+    unsigned              m_last_pos;
     unsigned              m_walksat;
     unsigned              m_ucb;
     double                m_ucb_constant;
@@ -1082,6 +1082,7 @@ public:
                 return 0;
         }
         
+        m_last_pos = pos;
         return as[pos];
 #if _REAL_RS_
         //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
@@ -1093,7 +1094,7 @@ public:
 #endif
     }
 
-    expr * get_new_unsat_assertion(ptr_vector<expr> const & as, expr * e) {
+    expr * get_new_unsat_assertion(ptr_vector<expr> const & as) {
         unsigned sz = as.size();
         if (sz == 1)
             return 0;
@@ -1101,7 +1102,7 @@ public:
         
         unsigned cnt_unsat = 0, pos = -1;
         for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i;	
+            if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
 
         if (pos == static_cast<unsigned>(-1))
             return 0;

From c441bb4388e6cd007c68e0974f4acf2c3a4e7d33 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 16:10:44 +0100
Subject: [PATCH 021/108] Backup before I touch early pruning ...

---
 src/tactic/sls/sls_compilation_settings.h |  3 ---
 src/tactic/sls/sls_engine.cpp             | 30 +++++++++++++----------
 src/tactic/sls/sls_engine.h               |  1 +
 src/tactic/sls/sls_evaluator.h            |  4 +--
 src/tactic/sls/sls_tracker.h              |  9 -------
 5 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index a649bc9ed..5c837b4b2 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,9 +22,6 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
 
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index af8ae1df2..5d4df237e 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -61,6 +61,7 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_walksat = p.walksat();
     m_walksat_repick = p.walksat_repick();
     m_paws_sp = p.paws_sp();
+    m_paws = m_paws_sp < 1024;
     m_wp = p.wp();
     m_vns_mc = p.vns_mc();
     m_vns_repick = p.vns_repick();
@@ -173,7 +174,6 @@ bool sls_engine::what_if(
 
     // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
-        m_tracker.reset_equal_scores();
         best_score = r;
         best_const = fd_inx;
         m_mpz_manager.set(best_value, temp);
@@ -244,16 +244,12 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
     else
     {
-#if _USE_ADDSUB_
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
         move_type mt = (move_type)rnd_mv;
 
         // inversion doesn't make sense, let's do a flip instead.
         if (mt == MV_INV) mt = MV_FLIP;
-#else
-        move_type mt = MV_FLIP;
-#endif
         unsigned bit = 0;
 
         switch (mt)
@@ -308,8 +304,9 @@ double sls_engine::find_best_move(
     unsigned bv_sz;
     double new_score = score;
 
-    m_tracker.reset_equal_scores();
-
+    //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size();
+    //for (unsigned j = 0; j < to_evaluate.size(); j++) {
+        //unsigned i = (j + offset) % to_evaluate.size();
     for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
@@ -328,7 +325,6 @@ double sls_engine::find_best_move(
         }
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
@@ -341,7 +337,6 @@ double sls_engine::find_best_move(
                 if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
-#endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
             if (what_if(fd, i, temp, new_score, best_const, best_value))
@@ -418,7 +413,7 @@ lbool sls_engine::search() {
 #if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
-        
+        // get candidate variables
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
         {
@@ -426,6 +421,7 @@ lbool sls_engine::search() {
             goto bailout;
         }
 
+        // random walk with probability wp / 1024
         if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
             mk_random_move(to_evaluate);
@@ -436,14 +432,18 @@ lbool sls_engine::search() {
         old_score = score;
         new_const = (unsigned)-1;
 
+        // find best increasing move
         score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 
+        // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously
         if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
             score = find_best_move_mc(to_evaluate, score, new_const, new_value);
    
+        // repick assertion if no increasing move was found previously
         if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
         {
             expr * q = m_tracker.get_new_unsat_assertion(m_assertions);
+            // only apply if another unsatisfied assertion actually exists
             if (q)
             {
                 ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q);
@@ -457,6 +457,7 @@ lbool sls_engine::search() {
             }
         }
 
+        // randomize if no increasing move was found
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
             if (m_walksat_repick)
@@ -466,16 +467,19 @@ lbool sls_engine::search() {
 
             score = m_tracker.get_top_sum() / m_assertions.size();
 
-            if (m_paws_sp < 1024)
+            // update assertion weights if a weigthing is enabled (sp < 1024)
+            if (m_paws)
             {
                 for (unsigned i = 0; i < sz; i++)
                 {
                     expr * q = m_assertions[i];
+                    // smooth weights with probability sp / 1024
                     if (m_tracker.get_random_uint(10) < m_paws_sp)
                     {
                         if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
                             m_tracker.decrease_weight(q);
                     }
+                    // increase weights otherwise
                     else
                     {
                         if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
@@ -484,6 +488,7 @@ lbool sls_engine::search() {
                 }
             }
         }
+        // otherwise, apply most increasing move
         else {
             func_decl * fd = to_evaluate[new_const];
             score = serious_score(fd, new_value);
@@ -507,7 +512,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     for (unsigned i = 0; i < g->size(); i++)
         assert_expr(g->form(i));    
 
-    verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
 
@@ -570,7 +574,7 @@ inline unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_next)
     {
-        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter.
+        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter.
         I leave the other versions as comments in case you want to try it again somewhen.
 #if _RESTART_SCHEME_ == 5
         m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index ff0e55f24..94f3fa626 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -76,6 +76,7 @@ protected:
     unsigned        m_wp;
     unsigned        m_vns_mc;
     unsigned        m_vns_repick;
+    unsigned        m_paws;
     unsigned        m_paws_sp;
     unsigned        m_restart_base;
     unsigned        m_restart_next;
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 37bfa5a2d..200a0e380 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -37,9 +37,7 @@ class sls_evaluator {
     powers              & m_powers;
     expr_ref_buffer       m_temp_exprs;
     vector<ptr_vector<expr> > m_traversal_stack;
-#if _EARLY_PRUNE_
     vector<ptr_vector<expr> > m_traversal_stack_bool;
-#endif
 
 public:
     sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : 
@@ -753,7 +751,7 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-                // should always have uplinks ...
+                // Andreas: Should actually always have uplinks ...
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 7b48057d4..a815c9ad3 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -92,7 +92,6 @@ private:
 #endif
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
-    unsigned              m_equal_scores;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -148,14 +147,6 @@ public:
         return sum / count;   
     }
 
-    void reset_equal_scores() {
-        m_equal_scores = 1;
-    }
-
-    unsigned inc_equal_scores() {
-        return ++m_equal_scores;
-    }
-
     inline void adapt_top_sum(expr * e, double add, double sub) {
         m_top_sum += m_weights.find(e) * (add - sub);
     }

From 9ebfb119dbd87babb52bed8eb55eee5c061cbcba Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Wed, 23 Apr 2014 14:52:18 +0100
Subject: [PATCH 022/108] Moved parameters to the right file. Almost clean.

---
 src/tactic/sls/sls_compilation_settings.h |  5 +--
 src/tactic/sls/sls_engine.cpp             | 38 +++++++++++------------
 src/tactic/sls/sls_engine.h               |  3 +-
 src/tactic/sls/sls_evaluator.h            |  5 ---
 src/tactic/sls/sls_params.pyg             | 20 ++++++++++--
 src/tactic/sls/sls_tracker.h              | 33 +++++++++-----------
 6 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 5c837b4b2..707802cf4 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,10 +22,7 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+// should we use unsat-structures as done in SLS 4 SAT?
 #define _REAL_RS_ 0
 
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 5d4df237e..a1c72609c 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -70,6 +70,8 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_next = m_restart_base;
     m_restart_init = p.restart_init();
 
+    m_early_prune = p.early_prune();
+
     // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
     if (m_walksat_repick && !m_walksat)
         NOT_IMPLEMENTED_YET();
@@ -117,7 +119,7 @@ double sls_engine::top_score() {
 
     m_tracker.set_top_sum(top_sum);
 
-    return top_sum / (double)sz;
+    return top_sum;
 }
 
 double sls_engine::rescore() {
@@ -129,21 +131,21 @@ double sls_engine::rescore() {
 double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return m_tracker.get_top_sum();
 }
 
 double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return m_tracker.get_top_sum();
 }
 
 double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
-        return (m_tracker.get_top_sum() / m_assertions.size());
+        return m_tracker.get_top_sum();
     else
-        return 0.0;
+        return -DBL_MAX;
 }
 
 // checks whether the score outcome of a given move is better than the previous score
@@ -160,11 +162,11 @@ bool sls_engine::what_if(
     m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 #endif
 
-#if _EARLY_PRUNE_
-    double r = incremental_score_prune(fd, temp);
-#else
-    double r = incremental_score(fd, temp);
-#endif   
+    double r;
+    if (m_early_prune)
+        r = incremental_score_prune(fd, temp);
+    else
+        r = incremental_score(fd, temp);
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
             " --> " << r << std::endl;);
@@ -342,11 +344,8 @@ double sls_engine::find_best_move(
             if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
         }
-
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
-        // Andreas: does not hold anymore now that we use top level score caching
-        //SASSERT(check == score);
+        incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -381,9 +380,8 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
                 }
             }
         }
-
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
+        incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -408,7 +406,10 @@ lbool sls_engine::search() {
         checkpoint();
         m_stats.m_moves++;
         if (m_stats.m_moves % m_restart_base == 0)
+        {
             m_tracker.ucb_forget(m_assertions);
+            //score = rescore();
+        }
 
 #if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
@@ -425,7 +426,7 @@ lbool sls_engine::search() {
         if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
             mk_random_move(to_evaluate);
-            score = m_tracker.get_top_sum() / sz;
+            score = m_tracker.get_top_sum();
             continue;
         }
 
@@ -465,7 +466,7 @@ lbool sls_engine::search() {
             else
                 m_evaluator.randomize_local(to_evaluate);
 
-            score = m_tracker.get_top_sum() / m_assertions.size();
+            score = m_tracker.get_top_sum();
 
             // update assertion weights if a weigthing is enabled (sp < 1024)
             if (m_paws)
@@ -513,7 +514,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         assert_expr(g->form(i));    
 
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-    verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
 
     lbool res = operator()();
 
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 94f3fa626..ac8610871 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -81,8 +81,7 @@ protected:
     unsigned        m_restart_base;
     unsigned        m_restart_next;
     unsigned        m_restart_init;
-
-    ptr_vector<mpz> m_old_values;
+    unsigned        m_early_prune;
 
     typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 200a0e380..e4cf3c466 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -554,9 +554,7 @@ public:
                 if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
-#if _EARLY_PRUNE_
                 m_tracker.set_score_prune(cur, new_score);
-#endif            
 
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -599,9 +597,6 @@ public:
                 if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
-#if _EARLY_PRUNE_
-                m_tracker.set_score_prune(cur, new_score);
-#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index cc3e05966..98875b20d 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -2,7 +2,21 @@ def_module_params('sls',
                   export=True,
                   description='Experimental Stochastic Local Search Solver (for QFBV only).',
                   params=(max_memory_param(),
-                          ('restarts', UINT, UINT_MAX, '(max) number of restarts'),
-                          ('plateau_limit', UINT, 10, 'pleateau limit'),
-			  ('random_seed', UINT, 0, 'random seed')
+						('max_restarts', UINT, UINT_MAX, 'maximum number of restarts'),
+						('walksat', BOOL, 1, 'use walksat assertion selection (instead of gsat)'),
+						('walksat_ucb', BOOL, 1, 'use bandit heuristic for walksat assertion selection (instead of random)'),
+						('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
+						('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'),
+						('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'),
+						('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'),
+						('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'),
+						('paws_init', UINT, 40, 'initial/minimum assertion weights'),
+						('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'),
+						('wp', UINT, 0, 'random walk with probability wp / 1024'),
+						('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'),
+						('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'),
+						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
+						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
+						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
+						('random_seed', UINT, 0, 'random seed')
 			  ))
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index a815c9ad3..507596273 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -44,11 +44,9 @@ class sls_tracker {
         unsynch_mpz_manager * m;
         mpz value;
         double score;
-#if _EARLY_PRUNE_
         double score_prune;
         unsigned has_pos_occ;
         unsigned has_neg_occ;
-#endif
         unsigned distance; // max distance from any root
         unsigned touched;
         value_score & operator=(const value_score & other) {
@@ -122,6 +120,7 @@ public:
         m_paws_init = p.paws_init();
     }
 
+    /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently.
     unsigned get_formula_size() {
         return m_scores.size();
     }
@@ -145,7 +144,7 @@ public:
         }
 
         return sum / count;   
-    }
+    }*/
 
     inline void adapt_top_sum(expr * e, double add, double sub) {
         m_top_sum += m_weights.find(e) * (add - sub);
@@ -417,6 +416,8 @@ public:
         }
     }
 
+    /* Andreas: Used this at some point to have values for the non-top-level expressions.
+                However, it did not give better performance but even cause some additional m/o - is not used currently.
     void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
         if (m_manager.is_and(e) || m_manager.is_or(e)) {
             app * a = to_app(e);
@@ -445,7 +446,7 @@ public:
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
-    }
+    }*/
 
     void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
@@ -455,8 +456,6 @@ public:
             expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
-            else
-                printf("this is already in ...\n");
             for_each_expr(proc, visited, e);
         }
 
@@ -464,7 +463,6 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = as[i];
-            // Andreas: Maybe not fully correct.
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -488,15 +486,16 @@ public:
         for (unsigned i = 0; i < sz; i++)
         {
             expr * e = as[i];
-        	if (!m_weights.contains(e))
+
+            // initialize weights
+            if (!m_weights.contains(e))
         		m_weights.insert(e, m_paws_init);
+
+            // positive/negative occurences used for early pruning
+            setup_occs(as[i]);
         }
 
-#if _EARLY_PRUNE_
-        for (unsigned i = 0; i < sz; i++)
-            setup_occs(as[i]);
-#endif
-
+        // initialize ucb total touched value (individual ones are always initialized to 1)
         m_touched = m_ucb_init ? as.size() : 1;
     }
 
@@ -738,7 +737,6 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
             double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
@@ -764,7 +762,6 @@ public:
             const mpz & v1 = get_value(arg1);
             
             if (negated) {                    
-                //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0;
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << std::endl; );
@@ -1051,10 +1048,8 @@ public:
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
-                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
-#if _UCT_ == 3
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
-#endif
+                //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); 
                 if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
             if (pos == static_cast<unsigned>(-1))

From 3df2967be92549427ad1410c41f37c80df8e3726 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Fri, 25 Apr 2014 13:56:15 +0100
Subject: [PATCH 023/108] Cleaned up final SLS version. Enjoy!

---
 src/tactic/sls/sls_compilation_settings.h |  28 ----
 src/tactic/sls/sls_engine.cpp             |  43 ++++--
 src/tactic/sls/sls_engine.h               |   2 +
 src/tactic/sls/sls_evaluator.h            |   8 +-
 src/tactic/sls/sls_params.pyg             |   6 +-
 src/tactic/sls/sls_tracker.h              | 153 ++++++++--------------
 6 files changed, 94 insertions(+), 146 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 707802cf4..e69de29bb 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -1,28 +0,0 @@
-/*++
-Copyright (c) 2014 Microsoft Corporation
-
-Module Name:
-
-    sls_compilation_constants.h
-
-Abstract:
-
-    Stochastic Local Search (SLS) compilation constants
-
-Author:
-
-    Christoph (cwinter) 2014-03-19
-
-Notes:
-
-    This file should go away completely once we have evaluated all options.
-
---*/
-
-#ifndef _SLS_COMPILATION_SETTINGS_H_
-#define _SLS_COMPILATION_SETTINGS_H_
-
-// should we use unsat-structures as done in SLS 4 SAT?
-#define _REAL_RS_ 0
-
-#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index a1c72609c..269790902 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -71,6 +71,8 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_init = p.restart_init();
 
     m_early_prune = p.early_prune();
+    m_random_offset = p.random_offset();
+    m_rescore = p.rescore();
 
     // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
     if (m_walksat_repick && !m_walksat)
@@ -174,6 +176,9 @@ bool sls_engine::what_if(
     m_mpz_manager.del(old_value);
 #endif
 
+    // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection.
+    // r += 0.0001 * m_tracker.get_random_uint(8);
+
     // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
         best_score = r;
@@ -248,9 +253,15 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     {
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+
+        // Andreas: The other option would be to scale the probability for flips according to the bit-width.
+        /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt);
+        rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3);
+        if (rnd_mv > 3) rnd_mv = 0; */
+
         move_type mt = (move_type)rnd_mv;
 
-        // inversion doesn't make sense, let's do a flip instead.
+        // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true?
         if (mt == MV_INV) mt = MV_FLIP;
         unsigned bit = 0;
 
@@ -306,10 +317,13 @@ double sls_engine::find_best_move(
     unsigned bv_sz;
     double new_score = score;
 
-    //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size();
-    //for (unsigned j = 0; j < to_evaluate.size(); j++) {
-        //unsigned i = (j + offset) % to_evaluate.size();
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
+    unsigned sz = to_evaluate.size();
+    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
+    for (unsigned j = 0; j < sz; j++) {
+        unsigned i = j + offset;
+        if (i >= sz) i -= sz;
+    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -361,7 +375,13 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
     unsigned bv_sz;
     double new_score = score;
 
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
+    unsigned sz = to_evaluate.size();
+    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
+    for (unsigned j = 0; j < sz; j++) {
+        unsigned i = j + offset;
+        if (i >= sz) i -= sz;
+    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -405,15 +425,16 @@ lbool sls_engine::search() {
     while (check_restart(m_stats.m_moves)) {
         checkpoint();
         m_stats.m_moves++;
+
+        // Andreas: Every base restart interval ...
         if (m_stats.m_moves % m_restart_base == 0)
         {
+            // ... potentially smooth the touched counters ...
             m_tracker.ucb_forget(m_assertions);
-            //score = rescore();
+            // ... or normalize the top-level score.
+            if (m_rescore) score = rescore();
         }
 
-#if _REAL_RS_
-        //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
         // get candidate variables
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
@@ -513,8 +534,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     for (unsigned i = 0; i < g->size(); i++)
         assert_expr(g->form(i));    
 
-    verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-
     lbool res = operator()();
 
     if (res == l_true) {
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index ac8610871..8158808fa 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -82,6 +82,8 @@ protected:
     unsigned        m_restart_next;
     unsigned        m_restart_init;
     unsigned        m_early_prune;
+    unsigned        m_random_offset;
+    unsigned        m_rescore;
 
     typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index e4cf3c466..61afb7457 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -22,7 +22,6 @@ Notes:
 
 #include"model_evaluator.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 #include"sls_tracker.h"
 
@@ -540,19 +539,16 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 
-#if _REAL_RS_
+                new_score = m_tracker.score(cur);
                 if (m_tracker.is_top_expr(cur))
                 {
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     if (m_mpz_manager.eq(new_value,m_one))
                         m_tracker.make_assertion(cur);
                     else
                         m_tracker.break_assertion(cur);
                 }
-#endif
 
-                new_score = m_tracker.score(cur);
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
 
diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index 98875b20d..ad7a22675 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -8,15 +8,19 @@ def_module_params('sls',
 						('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
 						('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'),
 						('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'),
+						('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'),
 						('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'),
 						('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'),
 						('paws_init', UINT, 40, 'initial/minimum assertion weights'),
 						('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'),
-						('wp', UINT, 0, 'random walk with probability wp / 1024'),
+						('wp', UINT, 100, 'random walk with probability wp / 1024'),
 						('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'),
 						('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'),
 						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
 						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
 						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
+						('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'),
+						('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'),
+						('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'),
 						('random_seed', UINT, 0, 'random seed')
 			  ))
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 507596273..4356bcc9b 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -80,14 +80,13 @@ private:
     double                m_ucb_constant;
     unsigned              m_ucb_init;
     double                m_ucb_forget;
+    double                m_ucb_noise;
     unsigned              m_touched;
     double                m_scale_unsat;
     unsigned              m_paws_init;
-#if _REAL_RS_
-    ptr_vector<expr>	  m_unsat_expr;
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
-#endif
+    unsigned              m_track_unsat;
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
 
@@ -116,8 +115,12 @@ public:
         m_ucb_constant = p.walksat_ucb_constant();
         m_ucb_init = p.walksat_ucb_init();
         m_ucb_forget = p.walksat_ucb_forget();
+        m_ucb_noise = p.walksat_ucb_noise();
         m_scale_unsat = p.scale_unsat();
         m_paws_init = p.paws_init();
+        // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy.
+        // If you want to use it, you will also need to change comments in the assertion selection.
+        m_track_unsat = 0;//p.track_unsat();
     }
 
     /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently.
@@ -254,53 +257,6 @@ public:
         return m_uplinks.find(n);
     }
 
-#if _REAL_RS_
-    void debug_real(goal_ref const & g, unsigned flip)
-    {
-        unsigned count = 0;
-        for (unsigned i = 0; i < g->size(); i++)
-        {
-            expr * e = g->form(i);
-            if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e))
-            {
-                printf("iteration %d: ", flip);
-                printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size());
-                exit(4);
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e))
-            {
-                printf("iteration %d: ", flip);
-                printf("form %d is unsat but not in unsat list\n", i);
-                exit(4);
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e))
-            {
-                unsigned pos = m_where_false.find(e);
-                expr * q = m_list_false[pos];
-                if (q != e)
-                {
-                    printf("iteration %d: ", flip);
-                    printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos);
-                    exit(4);
-                }
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero))
-                count++;
-        }
-
-        // should be true now that duplicate assertions are removed
-        if (count != m_where_false.size())
-        {
-                printf("iteration %d: ", flip);
-                printf("%d are unsat but list is of size %d\n", count, m_where_false.size());
-                exit(4);
-        }
-    }
-#endif
-
     inline void ucb_forget(ptr_vector<expr> & as) {
         if (m_ucb_forget < 1.0)
         {
@@ -474,14 +430,15 @@ public:
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
-#if _REAL_RS_
-        m_list_false = new expr*[sz];
-        //for (unsigned i = 0; i < sz; i++)
-        //{
-        //	if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-        //		break_assertion(g->form(i));
-        //}
-#endif
+        if (m_track_unsat)
+        {
+            m_list_false = new expr*[sz];
+            for (unsigned i = 0; i < sz; i++)
+            {
+        	    if (m_mpz_manager.eq(get_value(as[i]), m_zero))
+                    break_assertion(as[i]);
+            }
+        }
 
         for (unsigned i = 0; i < sz; i++)
         {
@@ -515,44 +472,36 @@ public:
         return m_weights.find(e);
     }
 
-#if _REAL_RS_
     void make_assertion(expr * e)
     {
-        if (m_where_false.contains(e))
+        if (m_track_unsat)
         {
-            unsigned pos = m_where_false.find(e);
-            m_where_false.erase(e);
-            if (pos != m_where_false.size())
+            if (m_where_false.contains(e))
             {
-                expr * q = m_list_false[m_where_false.size()];
-                m_list_false[pos] = q;
-                m_where_false.find(q) = pos;
-                //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos);
+                unsigned pos = m_where_false.find(e);
+                m_where_false.erase(e);
+                if (pos != m_where_false.size())
+                {
+                    expr * q = m_list_false[m_where_false.size()];
+                    m_list_false[pos] = q;
+                    m_where_false.find(q) = pos;
+                }
             }
-            //else
-                //printf("Erasing %d from %d to %d\n", e, pos);
-//			m_list_false[m_where_false.size()] = 0;
-//			printf("Going in %d\n", m_where_false.size());
         }
-        //if (m_unsat_expr.contains(e))
-            //m_unsat_expr.erase(e);
     }
 
     void break_assertion(expr * e)
     {
-        //printf("I'm broken... that's still fine.\n");
-        if (!m_where_false.contains(e))
+        if (m_track_unsat)
         {
-            //printf("This however is not so cool...\n");
-            unsigned pos = m_where_false.size();
-            m_list_false[pos] = e;
-            m_where_false.insert(e, pos);
-    //		printf("Going in %d\n", m_where_false.size());
+            if (!m_where_false.contains(e))
+            {
+                unsigned pos = m_where_false.size();
+                m_list_false[pos] = e;
+                m_where_false.insert(e, pos);
+            }
         }
-        //if (!m_unsat_expr.contains(e))
-            //m_unsat_expr.push_back(e);
     }
-#endif
 
     void show_model(std::ostream & out) {
         unsigned sz = get_num_constants();
@@ -1043,24 +992,38 @@ public:
         {
             value_score vscore;
             double max = -1.0;
+            // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit.
+            /* for (unsigned i = 0; i < m_where_false.size(); i++) {
+                expr * e = m_list_false[i]; */
             for (unsigned i = 0; i < sz; i++) {
                 expr * e = as[i];
-//            for (unsigned i = 0; i < m_where_false.size(); i++) {
-//                expr * e = m_list_false[i];
-                vscore = m_scores.find(e);
-                //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
-                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); 
-                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (m_mpz_manager.neq(get_value(e), m_one))
+                {
+                    vscore = m_scores.find(e);
+                    // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise.
+                    // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+                    double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); 
+                    if (q > max) { max = q; pos = i; }
+                }
             }
             if (pos == static_cast<unsigned>(-1))
                 return 0;
 
-            m_scores.find(as[pos]).touched++;
             m_touched++;
-//        return m_list_false[pos];
+            m_scores.find(as[pos]).touched++;
+            // Andreas: Also part of track_unsat data structures. Additionally disable the previous line!
+            /* m_last_pos = pos;
+            m_scores.find(m_list_false[pos]).touched++;
+            return m_list_false[pos]; */
         }
         else
         {
+            // Andreas: The track_unsat data structures for random assertion selection.
+            /* sz = m_where_false.size();
+            if (sz == 0)
+                return 0;
+            return m_list_false[get_random_uint(16) % sz]; */
+
             unsigned cnt_unsat = 0;
             for (unsigned i = 0; i < sz; i++)
                 if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
@@ -1070,14 +1033,6 @@ public:
         
         m_last_pos = pos;
         return as[pos];
-#if _REAL_RS_
-        //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-        //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-        sz = m_where_false.size();
-        if (sz == 0)
-            return 0;
-        return m_list_false[get_random_uint(16) % sz];
-#endif
     }
 
     expr * get_new_unsat_assertion(ptr_vector<expr> const & as) {

From a3f20774a8538eeec48191ae474ae2416750527c Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 17:17:47 +0100
Subject: [PATCH 024/108] BVSLS comments

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_params.pyg | 2 +-
 src/tactic/sls/sls_tracker.h  | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index ad7a22675..bf5bd181a 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -19,7 +19,7 @@ def_module_params('sls',
 						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
 						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
 						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
-						('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'),
+						('random_offset', BOOL, 1, 'use random offset for candidate evaluation'),
 						('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'),
 						('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'),
 						('random_seed', UINT, 0, 'random seed')
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 4356bcc9b..d58f94af2 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -831,7 +831,9 @@ public:
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 1);
             expr * child = a->get_arg(0);
-            if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
+            // Precondition: Assertion set is in NNF.
+            // Also: careful about the unsat assertion scaling further down.
+            if (m_manager.is_and(child) || m_manager.is_or(child)) 
                 NOT_IMPLEMENTED_YET();
             res = score_bool(child, true);
         }

From bfdea4242c9a26b43432040126a98fcf85a46075 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 18:03:35 +0100
Subject: [PATCH 025/108] removed unused file

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h | 0
 src/tactic/sls/sls_engine.cpp             | 1 -
 src/tactic/sls/sls_engine.h               | 1 -
 src/tactic/sls/sls_tracker.h              | 1 -
 4 files changed, 3 deletions(-)
 delete mode 100644 src/tactic/sls/sls_compilation_settings.h

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 269790902..67dba0237 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -27,7 +27,6 @@ Notes:
 #include"cooperate.h"
 #include"luby.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_params.hpp"
 #include"sls_engine.h"
 
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8158808fa..8a8a57e0e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -24,7 +24,6 @@ Notes:
 #include"model_converter.h"
 #include"goal.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_tracker.h"
 #include"sls_evaluator.h"
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index d58f94af2..186fae250 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -25,7 +25,6 @@ Notes:
 #include"bv_decl_plugin.h"
 #include"model.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 
 class sls_tracker {

From 4ff6a7c38dd86497eee7543a3fea54b75e03bcf2 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 18:11:30 +0100
Subject: [PATCH 026/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 186fae250..73355197a 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -25,6 +25,7 @@ Notes:
 #include"bv_decl_plugin.h"
 #include"model.h"
 
+#include"sls_params.hpp"
 #include"sls_powers.h"
 
 class sls_tracker {
@@ -1052,4 +1053,4 @@ public:
     }
 };
 
-#endif
\ No newline at end of file
+#endif

From c9c40877a70f08cef1d48af3ecd805ff173be931 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 21:49:35 +0100
Subject: [PATCH 027/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8a8a57e0e..b056c438e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -136,8 +136,8 @@ protected:
 
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
 
-    //inline double get_restart_armin(unsigned cnt_restarts);    
-    inline unsigned check_restart(unsigned curr_value);
+    //double get_restart_armin(unsigned cnt_restarts);    
+    unsigned check_restart(unsigned curr_value);
 };
 
 #endif

From 23dccdc7d519a86d779ae8b582663885e4548520 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 21:54:08 +0100
Subject: [PATCH 028/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 67dba0237..5b32e5790 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -16,6 +16,7 @@ Author:
 Notes:
 
 --*/
+#include<float.h>
 #include<iomanip>
 
 #include"map.h"

From 39b562da44d4cc63374c1904d378b9b41a406ee7 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 22:03:26 +0100
Subject: [PATCH 029/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 5b32e5790..c0c319ab4 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -581,7 +581,7 @@ lbool sls_engine::operator()() {
 }
 
 /* Andreas: Needed for Armin's restart scheme if we don't want to use loops.
-inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
+double sls_engine::get_restart_armin(unsigned cnt_restarts)
 {
     unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
     unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
@@ -589,7 +589,7 @@ inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
 }    
 */
 
-inline unsigned sls_engine::check_restart(unsigned curr_value)
+unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_next)
     {

From 6b37b847a0e3717fe718e97e0b2f9d49320edc91 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 11 Sep 2014 00:27:37 +0100
Subject: [PATCH 030/108] merge fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tactic.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 7ddf1a53d..9bbed20bb 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -79,10 +79,10 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = alloc(imp, m, m_params, m_stats);
+        sls_engine * d = alloc(sls_engine, m, m_params);
         #pragma omp critical (tactic_cancel)
         {
-            std::swap(d, m_imp);
+            std::swap(d, m_engine);
         }
         dealloc(d);
     }

From 75bae1b00c507dc4a85d7e9046063611b611507a Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 19 Dec 2014 12:32:57 +0000
Subject: [PATCH 031/108] BV-SLS optimization

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 73355197a..89ef57871 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -89,6 +89,7 @@ private:
     unsigned              m_track_unsat;
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
+    obj_hashtable<expr>   m_temp_seen;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -440,6 +441,7 @@ public:
             }
         }
 
+        m_temp_seen.reset();
         for (unsigned i = 0; i < sz; i++)
         {
             expr * e = as[i];
@@ -630,7 +632,14 @@ public:
                 app * a = to_app(n);
                 expr * const * args = a->get_args();
                 for (unsigned i = 0; i < a->get_num_args(); i++)
-                    setup_occs(args[i]);
+                {
+                    expr * child = args[i];
+                    if (!m_temp_seen.contains(child))
+                    {
+                        setup_occs(child, false);
+                        m_temp_seen.insert(child);
+                    }
+                }
             }
             else if (m_manager.is_not(n))
             {
@@ -638,8 +647,7 @@ public:
                 app * a = to_app(n);
                 SASSERT(a->get_num_args() == 1);
                 expr * child = a->get_arg(0);
-                if (m_manager.is_and(child) || m_manager.is_or(child))
-                    NOT_IMPLEMENTED_YET();
+                SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child));
                 setup_occs(child, true);
             }
             else

From d4ecc3c1be6f3fe4ecd1e018581795cbcdd98573 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 12 Jan 2015 15:59:20 +0000
Subject: [PATCH 032/108] Disabled BV-SLS as default tactic in anticipation for
 integration with the unstable branch.

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/portfolio/default_tactic.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 53da9a159..5a5cbcf94 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -32,8 +32,7 @@ Notes:
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
-  //                                      cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
+                                        cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),

From 66abc1c65eae3cec95d362ae849e689ce6d2113a Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 12 Jan 2015 17:03:27 +0000
Subject: [PATCH 033/108] Removed unnecessary file

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/api/dotnet/Properties/AssemblyInfo.cs | 38 -----------------------
 1 file changed, 38 deletions(-)
 delete mode 100644 src/api/dotnet/Properties/AssemblyInfo.cs

diff --git a/src/api/dotnet/Properties/AssemblyInfo.cs b/src/api/dotnet/Properties/AssemblyInfo.cs
deleted file mode 100644
index ee0e3f354..000000000
--- a/src/api/dotnet/Properties/AssemblyInfo.cs
+++ /dev/null
@@ -1,38 +0,0 @@
-using System;
-using System.Reflection;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-using System.Security.Permissions;
-
-// General Information about an assembly is controlled through the following 
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-[assembly: AssemblyTitle("Z3 .NET Interface")]
-[assembly: AssemblyDescription(".NET Interface to the Z3 Theorem Prover")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("Microsoft Corporation")]
-[assembly: AssemblyProduct("Z3")]
-[assembly: AssemblyCopyright("Copyright © Microsoft Corporation 2006")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-// Setting ComVisible to false makes the types in this assembly not visible 
-// to COM components.  If you need to access a type in this assembly from 
-// COM, set the ComVisible attribute to true on that type.
-[assembly: ComVisible(false)]
-
-// The following GUID is for the ID of the typelib if this project is exposed to COM
-[assembly: Guid("4853ed71-2078-40f4-8117-bc46646bce0e")]
-
-// Version information for an assembly consists of the following four values:
-//
-//      Major Version
-//      Minor Version 
-//      Build Number
-//      Revision
-//
-// You can specify all the values or you can default the Build and Revision Numbers 
-// by using the '*' as shown below:
-// [assembly: AssemblyVersion("4.2.0.0")]
-[assembly: AssemblyVersion("4.3.2.0")]
-[assembly: AssemblyFileVersion("4.3.2.0")]

From 40014d019ca8e656a3bc1e6c2966b716e597cc99 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 11 Feb 2014 17:44:59 +0000
Subject: [PATCH 034/108] sls tactic default

---
 src/tactic/portfolio/smt_strategic_solver.cpp | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index ae79446e3..52b0a3c90 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -37,11 +37,13 @@ Notes:
 #include"horn_tactic.h"
 #include"smt_solver.h"
 
+#include"sls_tactic.h"
+
 tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
-        return mk_qfbv_tactic(m, p);
+        return mk_qfbv_sls_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
     else if (logic=="QF_LIA")

From b002697e038554d0986fc974ed81bf2da0a62727 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 18 Feb 2014 14:01:47 +0000
Subject: [PATCH 035/108] some extensions/modifications. versions added.

---
 src/tactic/portfolio/default_tactic.cpp |   3 +-
 src/tactic/sls/sls_evaluator.h          |   4 +-
 src/tactic/sls/sls_tactic.cpp           | 146 ++++++++++++--
 src/tactic/sls/sls_tracker.h            | 249 +++++++++++++++++++++---
 versions/z3-crsat-0.01.txt              |  12 ++
 versions/z3-gsat-0.01.txt               |  10 +
 versions/z3-gsat-res-0.01.txt           |  10 +
 versions/z3-wsat-0.01.txt               |  12 ++
 versions/z3-wsat-0.01b.txt              |  12 ++
 versions/z3-wsat-0.01c.txt              |  12 ++
 versions/z3-wsat-0.01d.txt              |  11 ++
 versions/z3-wsat-0.01e.txt              |  11 ++
 versions/z3-wsat-0.02.txt               |  13 ++
 versions/z3-wsat-res-0.01.txt           |  13 ++
 14 files changed, 470 insertions(+), 48 deletions(-)
 create mode 100644 versions/z3-crsat-0.01.txt
 create mode 100644 versions/z3-gsat-0.01.txt
 create mode 100644 versions/z3-gsat-res-0.01.txt
 create mode 100644 versions/z3-wsat-0.01.txt
 create mode 100644 versions/z3-wsat-0.01b.txt
 create mode 100644 versions/z3-wsat-0.01c.txt
 create mode 100644 versions/z3-wsat-0.01d.txt
 create mode 100644 versions/z3-wsat-0.01e.txt
 create mode 100644 versions/z3-wsat-0.02.txt
 create mode 100644 versions/z3-wsat-res-0.01.txt

diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 9ecc16ecf..b28b7bec0 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -28,10 +28,11 @@ Notes:
 #include"probe_arith.h"
 #include"quant_tactics.h"
 #include"qffpa_tactic.h"
+#include"sls_tactic.h"
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
+                                        cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 77ff50454..61305386e 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -584,8 +584,8 @@ public:
         run_update(cur_depth);
     }
 
-     void randomize_local(goal_ref const & g) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g);
+     void randomize_local(goal_ref const & g, unsigned int flip) {
+        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
 
         // Randomize _all_ candidates:
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 6783d9621..c194af267 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -35,6 +35,17 @@ Notes:
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
 
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 30
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
+#define _VNS_ 0
+#define _WEIGHT_DIST_ 3
+#define _WEIGHT_DIST_FACTOR_ 0.1
+
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
 #include"sls_tracker.h"
@@ -257,7 +268,7 @@ class sls_tactic : public tactic {
             // inversion doesn't make sense, let's do a flip instead.
             if (mt == MV_INV) mt = MV_FLIP;
 
-            ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g);                
+			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
@@ -303,6 +314,82 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(new_value);
         }
 
+        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz, max_bv_sz = 0;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+				if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+
+					// try to flip lsb
+					mk_flip(srt, old_value, 0, temp);                
+	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+	                    new_bit = 0;
+	                    move = MV_FLIP;
+					}
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+
+#if _VNS_ == 1
+			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+			if (new_score <= score)
+			for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+				if (j < bv_sz)
+				{
+					mk_flip(srt, old_value, j, temp);                
+
+	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+	                    new_bit = j;
+	                    move = MV_FLIP;
+	                }
+				}
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+			m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -372,22 +459,29 @@ class sls_tactic : public tactic {
         
             unsigned plateau_cnt = 0;
 
-            while (plateau_cnt < m_plateau_limit) {                
-
+			// Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
                 do {
                     checkpoint();
             
                     old_score = score;
                     new_const = (unsigned)-1;
                         
-                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g);
+					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
 
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
 
+#if _VNS_
+                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
                     score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-
+#endif
                     if (new_const == static_cast<unsigned>(-1)) {
                         TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
                                         for (unsigned i = 0; i < g->size(); i++) {
@@ -400,9 +494,11 @@ class sls_tactic : public tactic {
                                         for (unsigned i = 0; i < g->size(); i++)
                                             tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
                                             m_tracker.get_score(g->form(i)) << std::endl; );
+						// Andreas: If new_const == -1, shouldn't score = old_score anyway?
                         score = old_score;
                     }
                     else {
+						// Andreas: Why does randomizing not count as a move? (Now it does.)
                         m_stats.m_moves++;
                         func_decl * fd = to_evaluate[new_const];
 
@@ -441,6 +537,7 @@ class sls_tactic : public tactic {
 
                     if (score >= 1.0) {
                         // score could theoretically be imprecise.
+						// Andreas: Can it only be imprecise in one direction?
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -451,19 +548,30 @@ class sls_tactic : public tactic {
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
+					/*
+					if (m_stats.m_moves % 100 == 0)
+					{
+						verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+						verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+					}*/
                 }
                 while (score > old_score && res == l_undef);                
-
-                if (score != old_score)
+				
+				// Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                if (score != old_score) {
+					report_tactic_progress("This should not happen I guess.", plateau_cnt);
                     plateau_cnt = 0;
-                else {
+				} else {
+					m_stats.m_moves++;
                     plateau_cnt++;
-                    if (plateau_cnt < m_plateau_limit) {
+					//report_tactic_progress("Plateau.", plateau_cnt);
+					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
-                        m_evaluator.randomize_local(g);
+						m_evaluator.randomize_local(g, m_stats.m_moves);
                         //mk_random_move(g);
                         score = top_score(g);
-                    }
+                    //}
                 }
             }
 
@@ -484,7 +592,8 @@ class sls_tactic : public tactic {
         
             do {
                 checkpoint();
-                if ((m_stats.m_restarts % 100) == 0)                        
+				// Andreas: I think restarts are too impotant to ignore 99% of them are happening...
+                //if ((m_stats.m_restarts % 100) == 0)                        
                     report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 
                 res = search(g);
@@ -492,9 +601,12 @@ class sls_tactic : public tactic {
                 if (res == l_undef)
                     m_tracker.randomize();
             }
-            while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
-            if (res == l_true) {                
+			verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+
+            if (res == l_true) {    
+				report_tactic_progress("Number of flips:", m_stats.m_moves);
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -628,7 +740,13 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
+#if _CNF_
+						// Andreas: We will probably never use this. CNF sucks.
+                        mk_cnf_tactic(m, p));
+#else
+						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
+#endif
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 7fbafec60..1061bd90e 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -28,8 +28,8 @@ class sls_tracker {
     random_gen            m_rng;
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
-    mpz                   m_zero, m_one, m_two;    
-    
+    mpz                   m_zero, m_one, m_two;   
+	    
     struct value_score { 
         value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { };
         ~value_score() { if (m) m->del(value); }
@@ -249,12 +249,46 @@ public:
         }
     }
 
-    void initialize(goal_ref const & g) {
+	void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
+		if (m_manager.is_and(e) || m_manager.is_or(e)) {
+			app * a = to_app(e);
+			expr * const * args = a->get_args();
+			unsigned int sz = a->get_num_args();
+			for (unsigned int i = 0; i < sz; i++) {
+		        expr * q = args[i];
+				initialize_recursive(proc, visited, q);
+			}
+		}
+		for_each_expr(proc, visited, e);
+ 	}
+
+	void initialize_recursive(expr * e) {
+		if (m_manager.is_and(e) || m_manager.is_or(e)) {
+			app * a = to_app(e);
+			expr * const * args = a->get_args();
+			unsigned int sz = a->get_num_args();
+			for (unsigned int i = 0; i < sz; i++) {
+		        expr * q = args[i];
+				initialize_recursive(q);
+			}
+		}
+		ptr_vector<func_decl> t;
+        m_constants_occ.insert_if_not_there(e, t);
+        find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
+        expr_fast_mark1 visited;
+        quick_for_each_expr(ffd_proc, visited, e);
+ 	}
+
+	void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);                
+            expr * e = g->form(i);
+			// Andreas: Maybe not fully correct.
+#if _FOCUS_ == 2
+			initialize_recursive(proc, visited, e);
+#endif
             for_each_expr(proc, visited, e);
         }
 
@@ -262,6 +296,10 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
+			// Andreas: Maybe not fully correct.
+#if _FOCUS_ == 2
+			initialize_recursive(e);
+#endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -382,8 +420,6 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
     }              
 
-#define _SCORE_AND_MIN
-
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
@@ -400,30 +436,41 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            #ifdef _SCORE_AND_MIN
-            double min = 1.0;
+			// Andreas: Seems to have no effect. Probably it does not even occur.
+#if _SCORE_AND_AVG_
+            double sum = 0.0;
+            for (unsigned i = 0; i < a->get_num_args(); i++)
+                sum += get_score(args[i]);
+            res = sum / (double) a->get_num_args();
+#else
+			double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur < min) min = cur;
             }
             res = min;
-            #else 
-            double sum = 0.0;
-            for (unsigned i = 0; i < a->get_num_args(); i++)
-                sum += get_score(args[i]);
-            res = sum / (double) a->get_num_args();
-            #endif
+#endif
         }
         else if (m_manager.is_or(n)) {
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            double max = 0.0;
+			// Andreas: Seems to have no effect. Probably it is still too similar to the original version.
+#if _SCORE_OR_MUL_
+			double inv = 1.0;
+            for (unsigned i = 0; i < a->get_num_args(); i++) {
+                double cur = get_score(args[i]);
+                inv *= (1.0 - get_score(args[i]));
+            }
+            res = 1.0 - inv;
+#else
+			double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur > max) max = cur;
             }
             res = max;
+#endif
         }
         else if (m_manager.is_ite(n)) {
             SASSERT(!negated);
@@ -468,7 +515,7 @@ public:
                     }
                     m_mpz_manager.machine_div(diff, m_two, diff);
                 }
-                res = 1.0 - (hamming_distance / (double) bv_sz);                    
+                res = 1.0 - (hamming_distance / (double) bv_sz);
                 #else                    
                 rational r(diff);
                 r /= m_powers(bv_sz);
@@ -503,7 +550,7 @@ public:
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
                     res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-                    m_mpz_manager.del(diff);
+					m_mpz_manager.del(diff);
                 }
             }
             else {
@@ -564,7 +611,7 @@ public:
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
-            m_mpz_manager.del(x);
+			m_mpz_manager.del(x);
             m_mpz_manager.del(y);                
         }
         else if (m_manager.is_not(n)) {                
@@ -598,6 +645,20 @@ public:
 
         SASSERT(res >= 0.0 && res <= 1.0);
 
+#if _WEIGHT_DIST_
+		app * a = to_app(n);
+		family_id afid = a->get_family_id();
+		if (afid == m_bv_util.get_family_id())
+#endif
+#if _WEIGHT_DIST_ == 1
+		if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+#elif _WEIGHT_DIST_ == 2
+		res *= res;
+#elif _WEIGHT_DIST_ == 3
+		if (res < 1.0) res = 0.0;
+#endif
+
+
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
@@ -647,7 +708,111 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g) {
+	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+        for (unsigned i = 0; i < sz; i++) {
+            expr * q = g->form(i);
+            if (m_mpz_manager.eq(get_value(q), m_one))
+                continue;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+        }
+        return m_temp_constants;
+	}
+
+	expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+			for (unsigned i = pos; i < sz; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+		            return q;
+			}
+			for (unsigned i = 0; i < pos; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+		            return q;
+            }
+			return 0;
+	}
+
+	ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+			expr * q = get_unsat_assertion(g, sz, pos);
+            // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
+			if (!q)
+				return m_temp_constants;
+
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+	        return m_temp_constants;
+	}
+
+	ptr_vector<func_decl> & go_deeper(expr * e) {
+			if (m_manager.is_bool(e)) {
+				if (m_manager.is_and(e)) {
+					app * a = to_app(e);
+					expr * const * args = a->get_args();
+				    // Andreas: might be used for guided branching
+					//for (unsigned i = 0; i < a->get_num_args(); i++) {
+						//double cur = get_score(args[i]);
+					//}
+					// Andreas: A random number is better here since reusing flip will cause patterns.
+					unsigned int sz = a->get_num_args();
+					unsigned int pos = get_random_uint(16) % sz;
+					for (unsigned int i = pos; i < sz; i++) {
+		                expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+					}
+					for (unsigned int i = 0; i < pos; i++) {
+						expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+		            }
+		        }
+				else if (m_manager.is_or(e)) {
+					app * a = to_app(e);
+					expr * const * args = a->get_args();
+					unsigned int sz = a->get_num_args();
+					unsigned int pos = get_random_uint(16) % sz;
+					for (unsigned int i = pos; i < sz; i++) {
+		                expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+					}
+					for (unsigned int i = 0; i < pos; i++) {
+						expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+		            }
+		        }
+			}
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+	        return m_temp_constants;
+	}
+
+	ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+		expr * q = get_unsat_assertion(g, sz, pos);
+        if (!q)
+			return m_temp_constants;
+
+		return go_deeper(q);
+	}
+
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
@@ -655,19 +820,41 @@ public:
         }
         else {
             m_temp_constants.reset();
-            for (unsigned i = 0; i < sz; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.eq(get_value(q), m_one))
-                    continue;
-                ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
-                unsigned sz2 = this_decls.size();
-                for (unsigned j = 0; j < sz2; j++) {
-                    func_decl * fd = this_decls[j];
-                    if (!m_temp_constants.contains(fd))
-                        m_temp_constants.push_back(fd);
-                }
+#if _FOCUS_ == 1
+#if _BFS_ == 3
+			unsigned int pos = 0;
+			double max = get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+				expr * e = g->form(i);
+                double q = get_score(e);
+				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-            return m_temp_constants;
+#elif _BFS_ == 2
+			unsigned int pos = 0;
+			double min = get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+				expr * e = g->form(i);
+                double q = get_score(e);
+				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+            }
+#elif _BFS_ == 1
+			unsigned int pos = flip % m_constants.size();
+#else
+			unsigned int pos = get_random_uint(16) % m_constants.size();
+#endif
+			return get_unsat_constants_walksat(g, sz, pos);
+#elif _FOCUS_ == 2
+#if _BFS_
+			unsigned int pos = flip % m_constants.size();
+#else
+			unsigned int pos = get_random_uint(16) % m_constants.size();
+#endif
+			return get_unsat_constants_crsat(g, sz, pos);
+#else
+			return get_unsat_constants_gsat(g, sz);
+#endif
         }
     }
 };
diff --git a/versions/z3-crsat-0.01.txt b/versions/z3-crsat-0.01.txt
new file mode 100644
index 000000000..49e1a1525
--- /dev/null
+++ b/versions/z3-crsat-0.01.txt
@@ -0,0 +1,12 @@
+More focused (_FOCUS_ == 2) WalkSAT version.
+Variables are chosen among candidates in only one unsatisfied bit-vector term.
+Flip rate slightly slower; probably due to larger hash-table and recursive formula structure.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 3
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-gsat-0.01.txt b/versions/z3-gsat-0.01.txt
new file mode 100644
index 000000000..eb806a67f
--- /dev/null
+++ b/versions/z3-gsat-0.01.txt
@@ -0,0 +1,10 @@
+Basic GSAT version.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 0
+#define _FOCUS_ 0
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-gsat-res-0.01.txt b/versions/z3-gsat-res-0.01.txt
new file mode 100644
index 000000000..6a211f2bc
--- /dev/null
+++ b/versions/z3-gsat-res-0.01.txt
@@ -0,0 +1,10 @@
+Basic GSAT version corresponding to Christoph's original code.
+Restarts after 100 plateaus.
+
+#define _CNF_ 0
+#define _BFS_ 0
+#define _FOCUS_ 0
+#define _RESTARTS_ 1
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt
new file mode 100644
index 000000000..141193f76
--- /dev/null
+++ b/versions/z3-wsat-0.01.txt
@@ -0,0 +1,12 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Flip rate increased by roughly 10%-300%.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt
new file mode 100644
index 000000000..2c0c0e7ad
--- /dev/null
+++ b/versions/z3-wsat-0.01b.txt
@@ -0,0 +1,12 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Chooses a random top level assertion instead of using a BFS approach (_BFS_ == 0).
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 0
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01c.txt b/versions/z3-wsat-0.01c.txt
new file mode 100644
index 000000000..223560e08
--- /dev/null
+++ b/versions/z3-wsat-0.01c.txt
@@ -0,0 +1,12 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+AND is scored by average; OR is scored by inverse multiplication.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 1
+#define _SCORE_OR_MUL_ 1
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01d.txt b/versions/z3-wsat-0.01d.txt
new file mode 100644
index 000000000..072191370
--- /dev/null
+++ b/versions/z3-wsat-0.01d.txt
@@ -0,0 +1,11 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion with MINIMAL top_score.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 2
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01e.txt b/versions/z3-wsat-0.01e.txt
new file mode 100644
index 000000000..b018c5e0d
--- /dev/null
+++ b/versions/z3-wsat-0.01e.txt
@@ -0,0 +1,11 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion with MAXIMAL top_score.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 3
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.02.txt b/versions/z3-wsat-0.02.txt
new file mode 100644
index 000000000..34dcb157c
--- /dev/null
+++ b/versions/z3-wsat-0.02.txt
@@ -0,0 +1,13 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Score function reduced to 0/1.
+No restarts.
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
+#define _WEIGHTED_DIST_ 1
\ No newline at end of file
diff --git a/versions/z3-wsat-res-0.01.txt b/versions/z3-wsat-res-0.01.txt
new file mode 100644
index 000000000..575180a59
--- /dev/null
+++ b/versions/z3-wsat-res-0.01.txt
@@ -0,0 +1,13 @@
+Basic WalkSAT version.
+Variables are chosen among candidates in only ONE top level assertion.
+Flip rate increased by roughly 10%-300% compared to GSAT.
+Restarts after 100 plateaus.
+Fps slightly decreased due to restarts. 
+
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 1
+#define _TIMELIMIT_ 300
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file

From e310ab5cd793d16e8a37e1a76023b5c477e2fb2e Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Sun, 9 Mar 2014 15:42:51 +0000
Subject: [PATCH 036/108] plenty of new stuff

---
 src/sat/tactic/sat_tactic.cpp                 |   4 +-
 src/tactic/portfolio/default_tactic.cpp       |   1 +
 src/tactic/portfolio/smt_strategic_solver.cpp |   1 +
 src/tactic/sls/sls_evaluator.h                | 323 ++++++++-
 src/tactic/sls/sls_tactic.cpp                 | 661 ++++++++++++++++--
 src/tactic/sls/sls_tracker.h                  | 345 ++++++++-
 versions/z3-wsat-0.01.txt                     |   4 +-
 versions/z3-wsat-0.01b.txt                    |   4 +-
 8 files changed, 1235 insertions(+), 108 deletions(-)

diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp
index d48994861..717bf7007 100644
--- a/src/sat/tactic/sat_tactic.cpp
+++ b/src/sat/tactic/sat_tactic.cpp
@@ -66,7 +66,9 @@ class sat_tactic : public tactic {
             CASSERT("sat_solver", m_solver.check_invariant());
             IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver.display_status(verbose_stream()););
             TRACE("sat_dimacs", m_solver.display_dimacs(tout););
-            
+			//m_solver.display_dimacs(std::cerr);
+            //exit(0);
+
             lbool r = m_solver.check();
             if (r == l_false) {
                 g->assert_expr(m.mk_false(), 0, 0);
diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index b28b7bec0..53da9a159 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -33,6 +33,7 @@ Notes:
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
                                         cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
+  //                                      cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),
diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index 52b0a3c90..f63b4fd8c 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -43,6 +43,7 @@ tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
+   //     return mk_qfbv_tactic(m, p);
         return mk_qfbv_sls_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 61305386e..eec9524a9 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -34,6 +34,9 @@ class sls_evaluator {
     powers              & m_powers;
     expr_ref_buffer       m_temp_exprs;
     vector<ptr_vector<expr> > m_traversal_stack;
+#if _EARLY_PRUNE_
+    vector<ptr_vector<expr> > m_traversal_stack_bool;
+#endif
 
 public:
     sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : 
@@ -519,11 +522,15 @@ public:
         }    
     }
 
-    void run_update(unsigned cur_depth) {
+    void run_serious_update(unsigned cur_depth) {
         // precondition: m_traversal_stack contains the entry point(s)
         expr_fast_mark1 visited;
         mpz new_value;
 
+#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
+		double new_score;
+#endif
+
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -533,8 +540,92 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-                m_tracker.set_score(cur, m_tracker.score(cur));
 
+#if _REAL_RS_ || _REAL_PBFS_
+				if (!m_tracker.has_uplinks(cur))
+				{
+					if (m_mpz_manager.eq(new_value,m_one))
+						m_tracker.make_assertion(cur);
+					else
+						m_tracker.break_assertion(cur);
+				}
+#endif
+
+#if _EARLY_PRUNE_
+				new_score = m_tracker.score(cur);
+#if _CACHE_TOP_SCORE_
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+				m_tracker.set_score(cur, new_score);
+				m_tracker.set_score_prune(cur, new_score);
+#else
+#if _CACHE_TOP_SCORE_
+				new_score = m_tracker.score(cur);
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+				m_tracker.set_score(cur, new_score);
+#else
+				m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+#endif			
+                if (m_tracker.has_uplinks(cur)) {
+                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                    for (unsigned j = 0; j < ups.size(); j++) {
+                        expr * next = ups[j];
+                        unsigned next_d = m_tracker.get_distance(next);
+                        SASSERT(next_d < cur_depth);
+                        if (!visited.is_marked(next)) {
+                            m_traversal_stack[next_d].push_back(next);
+                            visited.mark(next);
+                        }
+                    }
+                }
+            }
+
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        m_mpz_manager.del(new_value);
+    }
+
+    void run_update(unsigned cur_depth) {
+        // precondition: m_traversal_stack contains the entry point(s)
+        expr_fast_mark1 visited;
+        mpz new_value;
+
+#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
+		double new_score;
+#endif
+
+        SASSERT(cur_depth < m_traversal_stack.size());
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
+
+            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+                expr * cur = cur_depth_exprs[i];
+
+                (*this)(to_app(cur), new_value);
+                m_tracker.set_value(cur, new_value);
+#if _EARLY_PRUNE_
+				new_score = m_tracker.score(cur);
+#if _CACHE_TOP_SCORE_
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+				m_tracker.set_score(cur, new_score);
+				m_tracker.set_score_prune(cur, new_score);
+#else
+#if _CACHE_TOP_SCORE_
+				new_score = m_tracker.score(cur);
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+				m_tracker.set_score(cur, new_score);
+#else
+				m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+#endif			
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -569,8 +660,11 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-
+#if _REAL_RS_ || _REAL_PBFS_
+		run_serious_update(max_depth);
+#else
         run_update(max_depth);
+#endif
     }
 
     void update(func_decl * fd, const mpz & new_value) {
@@ -584,6 +678,196 @@ public:
         run_update(cur_depth);
     }
 
+    void serious_update(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+        if (m_traversal_stack.size() <= cur_depth) 
+            m_traversal_stack.resize(cur_depth+1);
+        m_traversal_stack[cur_depth].push_back(ep);
+
+        run_serious_update(cur_depth);
+    }
+
+#if _EARLY_PRUNE_
+    unsigned run_update_bool_prune(unsigned cur_depth) {
+        expr_fast_mark1 visited;
+
+		double prune_score, new_score;
+		unsigned pot_benefits = 0;
+ 		SASSERT(cur_depth < m_traversal_stack_bool.size());
+ 
+        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+
+        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+            expr * cur = cur_depth_exprs[i];
+
+			new_score = m_tracker.score(cur); 
+#if _CACHE_TOP_SCORE_
+			if (!m_tracker.has_uplinks(cur))
+				m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+			prune_score = m_tracker.get_score_prune(cur);
+            m_tracker.set_score(cur, new_score);
+
+			if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+				pot_benefits = 1;
+			if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+				pot_benefits = 1;
+
+            if (m_tracker.has_uplinks(cur)) {
+                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                for (unsigned j = 0; j < ups.size(); j++) {
+                    expr * next = ups[j];
+                    unsigned next_d = m_tracker.get_distance(next);
+                    SASSERT(next_d < cur_depth);
+                    if (!visited.is_marked(next)) {
+						m_traversal_stack_bool[next_d].push_back(next);
+                        visited.mark(next);
+                    }
+                }
+            }
+			else
+			{
+			}
+		}
+
+		cur_depth_exprs.reset();
+        cur_depth--;
+ 
+		while (cur_depth != static_cast<unsigned>(-1)) {
+			ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+			if (pot_benefits)
+			{
+				unsigned cur_size = cur_depth_exprs.size();
+				for (unsigned i = 0; i < cur_size; i++) {
+					expr * cur = cur_depth_exprs[i];
+
+#if _CACHE_TOP_SCORE_
+					new_score = m_tracker.score(cur); 
+					if (!m_tracker.has_uplinks(cur))
+						m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+					m_tracker.set_score(cur, new_score);
+#else
+					m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+					if (m_tracker.has_uplinks(cur)) {
+						ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+						for (unsigned j = 0; j < ups.size(); j++) {
+							expr * next = ups[j];
+							unsigned next_d = m_tracker.get_distance(next);
+							SASSERT(next_d < cur_depth);
+							if (!visited.is_marked(next)) {
+								m_traversal_stack_bool[next_d].push_back(next);
+								visited.mark(next);
+							}
+						}
+					}
+				}
+			}
+			cur_depth_exprs.reset();
+			cur_depth--;
+		}
+
+		return pot_benefits;
+    }
+
+    void run_update_prune(unsigned max_depth) {
+        // precondition: m_traversal_stack contains the entry point(s)
+        expr_fast_mark1 visited;
+        mpz new_value;
+
+		unsigned cur_depth = max_depth;
+        SASSERT(cur_depth < m_traversal_stack.size());
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
+
+            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+                expr * cur = cur_depth_exprs[i];
+
+                (*this)(to_app(cur), new_value);
+                m_tracker.set_value(cur, new_value);
+				// should always have uplinks ...
+                if (m_tracker.has_uplinks(cur)) {
+                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                    for (unsigned j = 0; j < ups.size(); j++) {
+                        expr * next = ups[j];
+                        unsigned next_d = m_tracker.get_distance(next);
+                        SASSERT(next_d < cur_depth);
+                        if (!visited.is_marked(next)) {
+							if (m_manager.is_bool(next))
+								m_traversal_stack_bool[max_depth].push_back(next);
+							else
+								m_traversal_stack[next_d].push_back(next);
+                            visited.mark(next);
+                        }
+                    }
+                }
+            }
+
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        m_mpz_manager.del(new_value);
+    }
+
+    unsigned update_prune(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+
+		if (m_traversal_stack_bool.size() <= cur_depth)
+            m_traversal_stack_bool.resize(cur_depth+1);
+		if (m_traversal_stack.size() <= cur_depth) 
+				m_traversal_stack.resize(cur_depth+1);
+
+		if (m_manager.is_bool(ep))
+	        m_traversal_stack_bool[cur_depth].push_back(ep);
+		else
+		{
+	        m_traversal_stack[cur_depth].push_back(ep);
+			run_update_prune(cur_depth);
+		}
+		return run_update_bool_prune(cur_depth);
+    }
+#endif
+
+	void randomize_local(expr * e, unsigned int flip) {
+        ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
+
+        // Randomize _one_ candidate:
+        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
+        func_decl * fd = unsat_constants[r];
+#if _PERC_CHANGE_
+        sort * srt = fd->get_range();
+		mpz temp;
+
+		if (m_manager.is_bool(srt))
+            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+		else
+        {
+			mpz temp2, mask;
+			unsigned bv_sz = m_bv_util.get_bv_size(srt);
+			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+
+			for (unsigned bit = 0; bit < bv_sz; bit++)
+				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+	            {
+	                m_mpz_manager.set(mask, m_powers(bit));
+					m_mpz_manager.bitwise_xor(temp, mask, temp2);
+	                m_mpz_manager.set(temp, temp2);
+		        }
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(temp2);
+		}
+#else
+		mpz temp = m_tracker.get_random(fd->get_range());
+#endif
+		update(fd, temp);
+        m_mpz_manager.del(temp);
+    } 
+
      void randomize_local(goal_ref const & g, unsigned int flip) {
         ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
 
@@ -603,8 +887,37 @@ public:
         // Randomize _one_ candidate:
         unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
         func_decl * fd = unsat_constants[r];
-        mpz temp = m_tracker.get_random(fd->get_range());
-        update(fd, temp);
+#if _PERC_CHANGE_
+        sort * srt = fd->get_range();
+		mpz temp;
+
+		if (m_manager.is_bool(srt))
+            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+		else
+        {
+			mpz temp2, mask;
+			unsigned bv_sz = m_bv_util.get_bv_size(srt);
+			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+
+			for (unsigned bit = 0; bit < bv_sz; bit++)
+				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+	            {
+	                m_mpz_manager.set(mask, m_powers(bit));
+					m_mpz_manager.bitwise_xor(temp, mask, temp2);
+	                m_mpz_manager.set(temp, temp2);
+		        }
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(temp2);
+		}
+#else
+		mpz temp = m_tracker.get_random(fd->get_range());
+#endif
+
+#if _REAL_RS_ || _REAL_PBFS_
+		serious_update(fd, temp);
+#else
+		update(fd, temp);
+#endif
         m_mpz_manager.del(temp);
 
         TRACE("sls", /*tout << "Randomization candidates: ";
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index c194af267..a08588a51 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -35,16 +35,102 @@ Notes:
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
 
-#define _CNF_ 0
-#define _BFS_ 1
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
 #define _FOCUS_ 1
+
+// do we use restarts?
+// 0 = no, otherwise the value defines the maximum number of moves
 #define _RESTARTS_ 0
-#define _TIMELIMIT_ 30
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
 #define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
 #define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
 #define _VNS_ 0
-#define _WEIGHT_DIST_ 3
-#define _WEIGHT_DIST_FACTOR_ 0.1
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 0
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.25
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 0
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 0.01
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+#define _PROBABILISTIC_UCT_ 0
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 1
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 1
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 1
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 1
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
+	InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+	InvalidConfiguration;
+#endif
+
 
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
@@ -57,12 +143,17 @@ class sls_tactic : public tactic {
         stopwatch       m_stopwatch;    
         unsigned        m_full_evals;
         unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+
         stats() :
             m_restarts(0),
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
+			m_umins(0),
+			m_mul2s(0),
+			m_mul3s(0),
+			m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -92,7 +183,9 @@ class sls_tactic : public tactic {
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;        
+		ptr_vector<mpz> m_old_values;
+		
+        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
 
         imp(ast_manager & m, params_ref const & p, stats & s) : 
             m_manager(m),
@@ -174,13 +267,20 @@ class sls_tactic : public tactic {
             #else
             double top_sum = 0.0;
             unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                top_sum += m_tracker.get_score(g->form(i));
+			for (unsigned i = 0; i < sz; i++) {
+				expr * e = g->form(i);
+                top_sum += m_tracker.get_score(e);
             }
-            TRACE("sls_top", tout << "Score distribution:"; 
+
+			TRACE("sls_top", tout << "Score distribution:"; 
                                     for (unsigned i = 0; i < sz; i++)
                                         tout << " " << m_tracker.get_score(g->form(i));
                                     tout << " AVG: " << top_sum / (double) sz << std::endl; );
+
+#if _CACHE_TOP_SCORE_
+			m_tracker.set_top_sum(top_sum);
+#endif
+
             return top_sum / (double) sz;
             #endif
         }
@@ -191,22 +291,54 @@ class sls_tactic : public tactic {
             return top_score(g);
         }
 
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
+        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+			m_evaluator.serious_update(fd, new_value);
             m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+			return (m_tracker.get_top_sum() / g->size());
+#else
             return top_score(g);
+#endif
         }
 
+        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+			m_evaluator.update(fd, new_value);
+            m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+			return (m_tracker.get_top_sum() / g->size());
+#else
+            return top_score(g);
+#endif
+        }
+
+#if _EARLY_PRUNE_
+        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_stats.m_incr_evals++;
+			if (m_evaluator.update_prune(fd, new_value))
+#if _CACHE_TOP_SCORE_
+				return (m_tracker.get_top_sum() / g->size());
+#else
+	            return top_score(g);
+#endif
+			else
+				return 0.0;
+        }
+#endif
+
+		// checks whether the score outcome of a given move is better than the previous score
         bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
-        
+
             #ifdef Z3DEBUG
             mpz old_value;
             m_mpz_manager.set(old_value, m_tracker.get_value(fd));
             #endif
 
+#if _EARLY_PRUNE_
+            double r = incremental_score_prune(g, fd, temp);
+#else
             double r = incremental_score(g, fd, temp);
-        
+#endif   
             #ifdef Z3DEBUG
             TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
                                         " --> " << r << std::endl; );
@@ -214,6 +346,22 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(old_value);
             #endif
 
+//            if (r >= best_score) {
+            if (r > best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+		// same as what_if, but only applied to the score of a specific atom, not the total score
+        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+            m_evaluator.update(fd, temp);
+			double r = m_tracker.get_score(e);
             if (r >= best_score) {
                 best_score = r;
                 best_const = fd_inx;            
@@ -224,7 +372,35 @@ class sls_tactic : public tactic {
             return false;
         }
 
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.add(old_value, add_value, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+			m_mpz_manager.del(temp);
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(mask2);
+
+		}
+
+		// Andreas: do we really need all those temporary mpzs?
+		void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.mul(old_value, m_two, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+			m_mpz_manager.del(temp);
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(mask2);
+        }
+
+        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            m_mpz_manager.div(old_value, m_two, result);
+        }
+
+		void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
             unsigned shift;        
             m_mpz_manager.add(old_value, m_one, incremented);
             if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
@@ -261,59 +437,73 @@ class sls_tactic : public tactic {
 
         void mk_random_move(goal_ref const & g) {
             unsigned rnd_mv = 0;
-            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-            move_type mt = (move_type) rnd_mv;
-
-            // inversion doesn't make sense, let's do a flip instead.
-            if (mt == MV_INV) mt = MV_FLIP;
+			if (m_stats.m_moves > 10000)
+				rnd_mv = 0;
 
 			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
-            mpz new_value;
-            unsigned bit = 0;
 
-            switch (mt)
-            {
-            case MV_FLIP: {
-                unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range());
-                bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                break;
-            }
-            case MV_INC: 
-                mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            case MV_DEC: 
-                mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            case MV_INV:
-                mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            default:
-                NOT_IMPLEMENTED_YET();
-            }
+			mpz new_value;
 
-            m_evaluator.update(fd, new_value);            
+			sort * srt = fd->get_range();
+            if (m_manager.is_bool(srt))
+				m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+			else
+			{
+#if _USE_ADDSUB_
+	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+				move_type mt = (move_type) rnd_mv;
 
-            TRACE("sls", tout << "Randomization candidates: ";
-                         for (unsigned i = 0; i < unsat_constants.size(); i++)
-                             tout << unsat_constants[i]->get_name() << ", ";
-                         tout << std::endl;
-                         tout << "Random move: ";
-                         switch (mt) {
-                         case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                         case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                         case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                         case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                         }
-                         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+				// inversion doesn't make sense, let's do a flip instead.
+				if (mt == MV_INV) mt = MV_FLIP;
+#else
+				mt = MV_FLIP;
+#endif
+				unsigned bit = 0;
 
-            m_mpz_manager.del(new_value);
-        }
+				switch (mt)
+				{
+					case MV_FLIP: {
+					unsigned bv_sz = m_bv_util.get_bv_size(srt);
+					bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+					mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+					break;
+				}
+				case MV_INC: 
+					mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				case MV_DEC: 
+					mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				case MV_INV:
+					mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				default:
+					NOT_IMPLEMENTED_YET();
+				}
 
+				TRACE("sls", tout << "Randomization candidates: ";
+							 for (unsigned i = 0; i < unsat_constants.size(); i++)
+								 tout << unsat_constants[i]->get_name() << ", ";
+							 tout << std::endl;
+							 tout << "Random move: ";
+							 switch (mt) {
+							 case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+							 case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+							 case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+							 case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+							 }
+							 tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+			}
+
+			m_evaluator.update(fd, new_value);            
+			m_mpz_manager.del(new_value);
+		}
+
+		// will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -359,6 +549,7 @@ class sls_tactic : public tactic {
                 SASSERT(check == score);
             }
 
+			// we can either check the condition once in the beginning or check it repeatedly after every bit
 #if _VNS_ == 1
 			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
 #else
@@ -390,9 +581,13 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
+		// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+			mpz temp2;
+#endif
             unsigned bv_sz;
             double new_score = score;
 
@@ -403,8 +598,12 @@ class sls_tactic : public tactic {
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-                    // What would happen if we flipped bit #i ?                
+#if _SKIP_BITS_
+				for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+#else
+				for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+					// What would happen if we flipped bit #i ?                
                     mk_flip(srt, old_value, j, temp);                
 
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
@@ -414,7 +613,8 @@ class sls_tactic : public tactic {
                 }
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
+#if _USE_ADDSUB_
+					if (!m_mpz_manager.is_even(old_value)) { 
                         // for odd values, try +1
                         mk_inc(bv_sz, old_value, temp);
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
@@ -426,16 +626,99 @@ class sls_tactic : public tactic {
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                             move = MV_DEC;
                     }
-
+#endif
                     // try inverting
                     mk_inv(bv_sz, old_value, temp);
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                         move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+                    mk_inc(bv_sz, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+                    // try multiplication by 2
+                    mk_mul2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_MUL2;
+
+#if _USE_MUL3_
+                    // try multiplication by 3
+                    mk_add(bv_sz, old_value, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_MUL3;
+#endif
+
+                    // try division by 2
+                    mk_div2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_DIV2;
+#endif
                 }
 
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
+				// Andreas: does not hold anymore now that we use top level score caching
+                //SASSERT(check == score);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+#if _USE_MUL3_
+            m_mpz_manager.del(temp2);
+#endif
+			return new_score;
+        }        
+
+		// same as find_best_move but only considers the score of the current expression instead of the overall score
+		double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz;
+			double new_score = m_tracker.get_score(e);
+			// Andreas: tie breaking not implemented yet
+			// double tie_score = top_score(g);
+            for (unsigned i = 0; i < to_evaluate.size(); i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+                for (unsigned j = 0; j < bv_sz; j++) {
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+                }
+
+                // reset to what it was before
+	            m_evaluator.update(fd, old_value);
             }
 
             m_mpz_manager.del(old_value);
@@ -443,7 +726,150 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
-        lbool search(goal_ref const & g) {        
+		// first try of intensification ... does not seem to be efficient
+		bool handle_plateau(goal_ref const & g)
+		{
+			unsigned sz = g->size();
+#if _BFS_
+			unsigned pos = m_stats.m_moves % sz;
+#else
+			unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+			expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+	        if (!e)
+				return 0;
+
+			expr * q = m_tracker.get_unsat_expression(e);
+			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+			for (unsigned i = 0; i < to_evaluate.size(); i++)
+			{
+				m_tracker.get_value(to_evaluate[i]);
+				m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+			}            
+			unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+			for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+			{
+				// Andreas: Could be extended to use (best) score but this is computationally more expensive.
+                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
+
+                if (new_const == static_cast<unsigned>(-1)) {
+					// Andreas: Actually this should never happen.
+					NOT_IMPLEMENTED_YET();
+                } else {
+                    m_stats.m_moves++;
+                    func_decl * fd = to_evaluate[new_const];
+
+                    switch (move) {
+                    case MV_FLIP: m_stats.m_flips++; break;
+                    case MV_INC: m_stats.m_incs++; break;
+                    case MV_DEC: m_stats.m_decs++; break;
+                    case MV_INV: m_stats.m_invs++; break;
+                    case MV_UMIN: m_stats.m_umins++; break;
+					case MV_MUL2: m_stats.m_mul2s++; break;
+					case MV_MUL3: m_stats.m_mul3s++; break;
+					case MV_DIV2: m_stats.m_div2s++; break;
+                    }
+                    
+					m_evaluator.update(fd, new_value);
+                }
+
+				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+					return 1;
+			}
+
+			for (unsigned i = 0; i < to_evaluate.size(); i++)
+				m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+
+			m_old_values.reset();
+
+			return 0;
+		}
+
+		// what_if version needed in the context of 2nd intensification try, combining local and global score
+        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
+                        double & best_score, mpz & best_value, unsigned i) {
+        
+            double global_score = incremental_score(g, fd, temp);
+			double local_score = m_tracker.get_score(e);
+            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+			if (new_score >= best_score) {
+                best_score = new_score;
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+		// find_best_move version needed in the context of 2nd intensification try
+        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+		{
+			mpz old_value, temp;
+            double best_score = 0;
+
+            sort * srt = fd->get_range();
+            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+			for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+                mk_flip(srt, old_value, j, temp);                
+                what_if(g, e, fd, temp, best_score, best_value, i); 
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+
+			return best_score;
+        }        
+
+		// second try to use intensification ... also not very effective
+		bool handle_plateau(goal_ref const & g, double old_score)
+		{
+			unsigned sz = g->size();
+#if _BFS_
+			unsigned new_const = m_stats.m_moves % sz;
+#else
+			unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+			expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+	        if (!e)
+				return 0;
+
+			expr * q = m_tracker.get_unsat_expression(e);
+			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+			new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+			func_decl * fd = to_evaluate[new_const];
+
+			mpz new_value;
+			//m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+			unsigned new_bit = 0;        
+			double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+			
+			for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+			{
+                new_score = find_best_move_local(g, q, fd, new_value, i);
+
+                m_stats.m_moves++;
+                m_stats.m_flips++;
+
+				global_score = incremental_score(g, fd, new_value);
+     			local_score = m_tracker.get_score(q);
+
+				SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+					return 1;
+			}
+
+			return 0;
+		}
+
+		// main search loop
+		lbool search(goal_ref const & g) {        
             lbool res = l_undef;
             double score = 0.0, old_score = 0.0;
             unsigned new_const = (unsigned)-1, new_bit = 0;        
@@ -463,16 +889,48 @@ class sls_tactic : public tactic {
 #if _RESTARTS_
 			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
+					if (m_stats.m_moves == 5590)
                     checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
             
+#if _TYPE_RSTEP_
+					if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+					{
+#if _TYPE_RSTEP_ == 1
+						m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+						mk_random_move(g);
+#endif
+                        score = top_score(g);
+
+	                    if (score >= 1.0) {
+	                        bool all_true = true;
+	                        for (unsigned i = 0; i < g->size() && all_true; i++)
+	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+	                                all_true=false;
+	                        if (all_true) {
+	                            res = l_true; // sat
+	                            goto bailout;
+							} else
+								TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+						}
+					}
+#endif
                     old_score = score;
                     new_const = (unsigned)-1;
                         
 					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-
+					if (!to_evaluate.size())
+					{
+						res = l_true;
+						goto bailout;
+					}
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
@@ -525,9 +983,17 @@ class sls_tactic : public tactic {
                         case MV_INC: m_stats.m_incs++; break;
                         case MV_DEC: m_stats.m_decs++; break;
                         case MV_INV: m_stats.m_invs++; break;
+                        case MV_UMIN: m_stats.m_umins++; break;
+						case MV_MUL2: m_stats.m_mul2s++; break;
+						case MV_MUL3: m_stats.m_mul3s++; break;
+						case MV_DIV2: m_stats.m_div2s++; break;
                         }
                     
-                        score = incremental_score(g, fd, new_value);    
+#if _REAL_RS_ || _REAL_PBFS_
+						score = serious_score(g, fd, new_value);
+#else
+						score = incremental_score(g, fd, new_value);    
+#endif
 
                         TRACE("sls", tout << "Score distribution:"; 
                                         for (unsigned i = 0; i < g->size(); i++)
@@ -535,9 +1001,10 @@ class sls_tactic : public tactic {
                                         tout << " TOP: " << score << std::endl; );                        
                     }
 
-                    if (score >= 1.0) {
+                    if (score >= 0.99999) {
+//                    if (score >= 1.0) {
                         // score could theoretically be imprecise.
-						// Andreas: Can it only be imprecise in one direction?
+						// Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -568,10 +1035,26 @@ class sls_tactic : public tactic {
 					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
                     //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
+#if _INTENSIFICATION_
+						handle_plateau(g, score);
+						//handle_plateau(g);
+#else
 						m_evaluator.randomize_local(g, m_stats.m_moves);
-                        //mk_random_move(g);
+#endif
+						//mk_random_move(g);
                         score = top_score(g);
-                    //}
+
+	                    if (score >= 1.0) {
+	                        bool all_true = true;
+	                        for (unsigned i = 0; i < g->size() && all_true; i++)
+	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+	                                all_true=false;
+	                        if (all_true) {
+	                            res = l_true; // sat
+	                            goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
                 }
             }
 
@@ -587,6 +1070,37 @@ class sls_tactic : public tactic {
                 return;
             }
 
+			verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+			verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+			verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+			verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+			verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+			verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+			verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+			verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+			verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+			verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+			verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+			verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+			verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+			verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+			verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+			verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+			verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+			verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+			verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+			verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+			verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+			verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+			verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+			verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+			verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+			verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+			verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+			
+#if _WEIGHT_DIST_ == 4
+					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
@@ -740,13 +1254,8 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-#if _CNF_
-						// Andreas: We will probably never use this. CNF sucks.
-                        mk_cnf_tactic(m, p));
-#else
 						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
-#endif
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 1061bd90e..b26912e5c 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -28,21 +28,32 @@ class sls_tracker {
     random_gen            m_rng;
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
-    mpz                   m_zero, m_one, m_two;   
+    mpz                   m_zero, m_one, m_two;
 	    
     struct value_score { 
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { };
+#if _EARLY_PRUNE_
+		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+#else
+		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
+#endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
+#if _EARLY_PRUNE_
+		double score_prune;
+		unsigned has_pos_occ;
+		unsigned has_neg_occ;
+#endif
         unsigned distance; // max distance from any root
+		unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
+			touched = other.touched;
             return *this;
         }
     };
@@ -60,6 +71,20 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
+#if _UCT_
+	unsigned              m_touched;
+#endif
+#if _REAL_RS_ || _REAL_PBFS_
+	ptr_vector<expr>	  m_unsat_expr;
+	obj_map<expr, unsigned>	m_where_false;
+	expr**					m_list_false;
+#endif
+#if _CACHE_TOP_SCORE_
+	double				  m_top_sum;
+#endif
+#if _WEIGHT_DIST_ == 4
+	double				  m_weight_dist_factor;
+#endif
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -79,6 +104,26 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+#if _WEIGHT_DIST_ == 4
+	inline void set_weight_dist_factor(double val) {
+		m_weight_dist_factor = val;
+	}
+#endif
+
+#if _CACHE_TOP_SCORE_
+	inline void adapt_top_sum(double add, double sub) {
+		m_top_sum += add - sub;
+	}
+
+	inline void set_top_sum(double new_score) {
+		m_top_sum = new_score;
+	}
+
+	inline double get_top_sum() {
+		return m_top_sum;
+	}
+#endif
+
     inline void set_value(expr * n, const mpz & r) {
         SASSERT(m_scores.contains(n));
         m_mpz_manager.set(m_scores.find(n).value, r);
@@ -123,6 +168,28 @@ public:
         return get_score(ep);
     }
 
+#if _EARLY_PRUNE_
+    inline void set_score_prune(expr * n, double score) {
+        SASSERT(m_scores.contains(n));
+        m_scores.find(n).score_prune = score;
+    }
+
+	inline double & get_score_prune(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).score_prune;
+    }
+
+	inline unsigned has_pos_occ(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).has_pos_occ;
+ 	}
+
+	inline unsigned has_neg_occ(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).has_neg_occ;
+ 	}
+#endif
+
     inline unsigned get_distance(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).distance;
@@ -297,7 +364,7 @@ public:
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
 			// Andreas: Maybe not fully correct.
-#if _FOCUS_ == 2
+#if _FOCUS_ == 2 || _INTENSIFICATION_
 			initialize_recursive(e);
 #endif
             ptr_vector<func_decl> t;
@@ -310,8 +377,57 @@ public:
         calculate_expr_distances(g);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
+
+#if _REAL_RS_ || _REAL_PBFS_
+		m_list_false = new expr*[sz];
+        for (unsigned i = 0; i < sz; i++)
+	  		if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+				break_assertion(g->form(i));
+#endif
+
+#if _EARLY_PRUNE_
+        for (unsigned i = 0; i < sz; i++)
+	  		setup_occs(g->form(i));
+#endif
+
+#if _UCT_
+		m_touched = 1;
+#endif
     }
 
+#if _REAL_RS_ || _REAL_PBFS_
+	void make_assertion(expr * e)
+	{
+		if (m_where_false.contains(e))
+		{
+			unsigned pos = m_where_false.find(e);
+			m_where_false.erase(e);
+			if (pos != m_where_false.size())
+			{
+				expr * q = m_list_false[m_where_false.size()];
+				m_list_false[pos] = q;
+				m_where_false.find(q) = pos;
+			}
+//			printf("Going in %d\n", m_where_false.size());
+		}
+		//if (m_unsat_expr.contains(e))
+			//m_unsat_expr.erase(e);
+	}
+
+	void break_assertion(expr * e)
+	{
+		if (!m_where_false.contains(e))
+		{
+			unsigned pos = m_where_false.size();
+			m_list_false[pos] = e;
+			m_where_false.insert(e, pos);
+	//		printf("Going in %d\n", m_where_false.size());
+		}
+		//if (!m_unsat_expr.contains(e))
+			//m_unsat_expr.push_back(e);
+	}
+#endif
+
     void show_model(std::ostream & out) {
         unsigned sz = get_num_constants();
         for (unsigned i = 0; i < sz; i++) {
@@ -420,10 +536,45 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
     }              
 
+#if _EARLY_PRUNE_
+	void setup_occs(expr * n, bool negated = false) {
+		if (m_manager.is_bool(n))
+		{
+			if (m_manager.is_and(n) || m_manager.is_or(n))
+			{
+	            SASSERT(!negated);
+	            app * a = to_app(n);
+	            expr * const * args = a->get_args();
+	            for (unsigned i = 0; i < a->get_num_args(); i++)
+					setup_occs(args[i]);
+			}
+			else if (m_manager.is_not(n))
+			{
+	            SASSERT(!negated);
+	            app * a = to_app(n);
+	            SASSERT(a->get_num_args() == 1);
+	            expr * child = a->get_arg(0);
+	            if (m_manager.is_and(child) || m_manager.is_or(child))
+	                NOT_IMPLEMENTED_YET();
+				setup_occs(child, true);
+			}
+			else
+			{
+				if (negated)
+					m_scores.find(n).has_neg_occ = 1;
+				else
+					m_scores.find(n).has_pos_occ = 1;
+			}
+		}
+        else
+            NOT_IMPLEMENTED_YET();
+    }
+#endif
+
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
-        double res = 0.0;
+		double res = 0.0;
             
         if (is_uninterp_const(n)) {
             const mpz & r = get_value(n);
@@ -488,7 +639,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-
+			
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -648,6 +799,7 @@ public:
 #if _WEIGHT_DIST_
 		app * a = to_app(n);
 		family_id afid = a->get_family_id();
+
 		if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
@@ -656,13 +808,14 @@ public:
 		res *= res;
 #elif _WEIGHT_DIST_ == 3
 		if (res < 1.0) res = 0.0;
+#elif _WEIGHT_DIST_ == 4
+		if (res < 1.0) res *= m_weight_dist_factor;
 #endif
 
-
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-
+	
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -708,6 +861,44 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
+	expr * get_unsat_expression(expr * e) {
+		if (m_manager.is_bool(e)) {
+			if (m_manager.is_and(e) || m_manager.is_or(e)) {
+				app * a = to_app(e);
+				expr * const * args = a->get_args();
+			    // Andreas: might be used for guided branching
+				//for (unsigned i = 0; i < a->get_num_args(); i++) {
+					//double cur = get_score(args[i]);
+				//}
+				// Andreas: A random number is better here since reusing flip will cause patterns.
+				unsigned int sz = a->get_num_args();
+				unsigned int pos = get_random_uint(16) % sz;
+				for (unsigned int i = pos; i < sz; i++) {
+	                expr * q = args[i];
+	                if (m_mpz_manager.neq(get_value(q), m_one))
+			            return get_unsat_expression(q);
+				}
+				for (unsigned int i = 0; i < pos; i++) {
+					expr * q = args[i];
+	                if (m_mpz_manager.neq(get_value(q), m_one))
+			            return get_unsat_expression(q);
+	            }
+	        }
+		}
+		return e;
+	}
+
+	ptr_vector<func_decl> & get_constants(expr * e) {
+        ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+        unsigned sz = this_decls.size();
+        for (unsigned i = 0; i < sz; i++) {
+            func_decl * fd = this_decls[i];
+            if (!m_temp_constants.contains(fd))
+                m_temp_constants.push_back(fd);
+        }
+        return m_temp_constants;
+	}
+
 	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
@@ -743,7 +934,6 @@ public:
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
 			if (!q)
 				return m_temp_constants;
-
 			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
@@ -754,6 +944,19 @@ public:
 	        return m_temp_constants;
 	}
 
+	ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
+			if (!e)
+				return m_temp_constants;
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz = this_decls.size();
+            for (unsigned j = 0; j < sz; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+	        return m_temp_constants;
+	}
+
 	ptr_vector<func_decl> & go_deeper(expr * e) {
 			if (m_manager.is_bool(e)) {
 				if (m_manager.is_and(e)) {
@@ -812,44 +1015,138 @@ public:
 		return go_deeper(q);
 	}
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+	ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
-            return get_constants();
+			if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+				return m_temp_constants;
+			else
+	            return get_constants();
         }
         else {
             m_temp_constants.reset();
 #if _FOCUS_ == 1
-#if _BFS_ == 3
-			unsigned int pos = 0;
-			double max = get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
+#if _UCT_
+			unsigned pos = -1;
+			value_score vscore;
+#if _PROBABILISTIC_UCT_
+			double sum_score = 0.0;
+			unsigned start_index = get_random_uint(16) % sz;
+			for (unsigned i = start_index; i < sz; i++)
+			{
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+					sum_score += q;
+					if (rand() <= (q * RAND_MAX / sum_score) + 1)
+						pos = i;
+				}	
+			}
+			for (unsigned i = 0; i < start_index; i++)
+			{
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+					sum_score += q;
+					if (rand() <= (q * RAND_MAX / sum_score) + 1)
+						pos = i;
+				}	
+			}
+#else
+			double max = -1.0;
+			for (unsigned i = 0; i < sz; i++) {
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+#if _UCT_ == 1
+				double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#elif _UCT_ == 2
+				double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#endif
+				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+            }
+#endif
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+
+#if _UCT_ == 1
+			m_scores.find(g->form(pos)).touched++;
+			m_touched++;
+#elif _UCT_ == 2
+			m_scores.find(g->form(pos)).touched = flip; 
+#endif
+			expr * e = g->form(pos);
+
+#elif _BFS_ == 3
+			unsigned int pos = -1;
+			double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
 				expr * e = g->form(i);
                 double q = get_score(e);
 				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
 #elif _BFS_ == 2
-			unsigned int pos = 0;
-			double min = get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
+			unsigned int pos = -1;
+			double min = 2.0;
+            for (unsigned i = 0; i < sz; i++) {
 				expr * e = g->form(i);
                 double q = get_score(e);
 				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
             }
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
 #elif _BFS_ == 1
-			unsigned int pos = flip % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = flip % m_constants.size();
+			unsigned int pos = flip % sz;
+			expr * e = get_unsat_assertion(g, sz, pos);
+#elif _UNIFORM_RANDOM_
+			unsigned cnt_unsat = 0, pos = -1;
+			for (unsigned i = 0; i < sz; i++)
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
+#elif _REAL_RS_
+			//unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+			//expr * e = get_unsat_assertion(g, sz, pos);
+			//expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+			sz = m_where_false.size();
+			if (sz == 0)
+				return m_temp_constants;
+			else
+				expr * e = m_list_false[get_random_uint(16) % sz];
+#elif _REAL_PBFS_
+			//unsigned pos = m_false_list[flip % m_cnt_false];
+			//expr * e = get_unsat_assertion(g, sz, pos);
+			//expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+			sz = m_where_false.size();
+			if (sz == 0)
+				return m_temp_constants;
+			else
+				expr * e = m_list_false[flip % sz];
 #else
-			unsigned int pos = get_random_uint(16) % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = get_random_uint(16) % m_constants.size();
+			unsigned int pos = get_random_uint(16) % sz;
+			expr * e = get_unsat_assertion(g, sz, pos);
 #endif
-			return get_unsat_constants_walksat(g, sz, pos);
+			return get_unsat_constants_walksat(e);
 #elif _FOCUS_ == 2
 #if _BFS_
-			unsigned int pos = flip % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = flip % m_constants.size();
+			unsigned int pos = flip % sz;
 #else
-			unsigned int pos = get_random_uint(16) % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = get_random_uint(16) % m_constants.size();
+			unsigned int pos = get_random_uint(16) % sz;
 #endif
 			return get_unsat_constants_crsat(g, sz, pos);
 #else
diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt
index 141193f76..fec38518d 100644
--- a/versions/z3-wsat-0.01.txt
+++ b/versions/z3-wsat-0.01.txt
@@ -9,4 +9,6 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
+
+BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt
index 2c0c0e7ad..8bcf2ffeb 100644
--- a/versions/z3-wsat-0.01b.txt
+++ b/versions/z3-wsat-0.01b.txt
@@ -9,4 +9,6 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
+
+BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file

From e33e637ad8b08528593f685f29f0dfec2015ce42 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 09:40:01 +0000
Subject: [PATCH 037/108] removed tabs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_evaluator.h | 268 ++++++-------
 src/tactic/sls/sls_tactic.cpp  | 572 ++++++++++++++--------------
 src/tactic/sls/sls_tracker.h   | 672 ++++++++++++++++-----------------
 3 files changed, 756 insertions(+), 756 deletions(-)

diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index eec9524a9..cdb08038f 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -528,7 +528,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -542,33 +542,33 @@ public:
                 m_tracker.set_value(cur, new_value);
 
 #if _REAL_RS_ || _REAL_PBFS_
-				if (!m_tracker.has_uplinks(cur))
-				{
-					if (m_mpz_manager.eq(new_value,m_one))
-						m_tracker.make_assertion(cur);
-					else
-						m_tracker.break_assertion(cur);
-				}
+                if (!m_tracker.has_uplinks(cur))
+                {
+                    if (m_mpz_manager.eq(new_value,m_one))
+                        m_tracker.make_assertion(cur);
+                    else
+                        m_tracker.break_assertion(cur);
+                }
 #endif
 
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -596,7 +596,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -609,23 +609,23 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -661,7 +661,7 @@ public:
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
 #if _REAL_RS_ || _REAL_PBFS_
-		run_serious_update(max_depth);
+        run_serious_update(max_depth);
 #else
         run_update(max_depth);
 #endif
@@ -693,27 +693,27 @@ public:
     unsigned run_update_bool_prune(unsigned cur_depth) {
         expr_fast_mark1 visited;
 
-		double prune_score, new_score;
-		unsigned pot_benefits = 0;
- 		SASSERT(cur_depth < m_traversal_stack_bool.size());
+        double prune_score, new_score;
+        unsigned pot_benefits = 0;
+         SASSERT(cur_depth < m_traversal_stack_bool.size());
  
         ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
 
         for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
             expr * cur = cur_depth_exprs[i];
 
-			new_score = m_tracker.score(cur); 
+            new_score = m_tracker.score(cur); 
 #if _CACHE_TOP_SCORE_
-			if (!m_tracker.has_uplinks(cur))
-				m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+            if (!m_tracker.has_uplinks(cur))
+                m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-			prune_score = m_tracker.get_score_prune(cur);
+            prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
-			if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
-				pot_benefits = 1;
-			if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
-				pot_benefits = 1;
+            if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+                pot_benefits = 1;
+            if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+                pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
                 ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -722,54 +722,54 @@ public:
                     unsigned next_d = m_tracker.get_distance(next);
                     SASSERT(next_d < cur_depth);
                     if (!visited.is_marked(next)) {
-						m_traversal_stack_bool[next_d].push_back(next);
+                        m_traversal_stack_bool[next_d].push_back(next);
                         visited.mark(next);
                     }
                 }
             }
-			else
-			{
-			}
-		}
+            else
+            {
+            }
+        }
 
-		cur_depth_exprs.reset();
+        cur_depth_exprs.reset();
         cur_depth--;
  
-		while (cur_depth != static_cast<unsigned>(-1)) {
-			ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-			if (pot_benefits)
-			{
-				unsigned cur_size = cur_depth_exprs.size();
-				for (unsigned i = 0; i < cur_size; i++) {
-					expr * cur = cur_depth_exprs[i];
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+            if (pot_benefits)
+            {
+                unsigned cur_size = cur_depth_exprs.size();
+                for (unsigned i = 0; i < cur_size; i++) {
+                    expr * cur = cur_depth_exprs[i];
 
 #if _CACHE_TOP_SCORE_
-					new_score = m_tracker.score(cur); 
-					if (!m_tracker.has_uplinks(cur))
-						m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-					m_tracker.set_score(cur, new_score);
+                    new_score = m_tracker.score(cur); 
+                    if (!m_tracker.has_uplinks(cur))
+                        m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.set_score(cur, new_score);
 #else
-					m_tracker.set_score(cur, m_tracker.score(cur));
+                    m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-					if (m_tracker.has_uplinks(cur)) {
-						ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-						for (unsigned j = 0; j < ups.size(); j++) {
-							expr * next = ups[j];
-							unsigned next_d = m_tracker.get_distance(next);
-							SASSERT(next_d < cur_depth);
-							if (!visited.is_marked(next)) {
-								m_traversal_stack_bool[next_d].push_back(next);
-								visited.mark(next);
-							}
-						}
-					}
-				}
-			}
-			cur_depth_exprs.reset();
-			cur_depth--;
-		}
+                    if (m_tracker.has_uplinks(cur)) {
+                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                        for (unsigned j = 0; j < ups.size(); j++) {
+                            expr * next = ups[j];
+                            unsigned next_d = m_tracker.get_distance(next);
+                            SASSERT(next_d < cur_depth);
+                            if (!visited.is_marked(next)) {
+                                m_traversal_stack_bool[next_d].push_back(next);
+                                visited.mark(next);
+                            }
+                        }
+                    }
+                }
+            }
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
 
-		return pot_benefits;
+        return pot_benefits;
     }
 
     void run_update_prune(unsigned max_depth) {
@@ -777,7 +777,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-		unsigned cur_depth = max_depth;
+        unsigned cur_depth = max_depth;
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -787,7 +787,7 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-				// should always have uplinks ...
+                // should always have uplinks ...
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -795,10 +795,10 @@ public:
                         unsigned next_d = m_tracker.get_distance(next);
                         SASSERT(next_d < cur_depth);
                         if (!visited.is_marked(next)) {
-							if (m_manager.is_bool(next))
-								m_traversal_stack_bool[max_depth].push_back(next);
-							else
-								m_traversal_stack[next_d].push_back(next);
+                            if (m_manager.is_bool(next))
+                                m_traversal_stack_bool[max_depth].push_back(next);
+                            else
+                                m_traversal_stack[next_d].push_back(next);
                             visited.mark(next);
                         }
                     }
@@ -817,23 +817,23 @@ public:
         expr * ep = m_tracker.get_entry_point(fd);
         unsigned cur_depth = m_tracker.get_distance(ep);
 
-		if (m_traversal_stack_bool.size() <= cur_depth)
+        if (m_traversal_stack_bool.size() <= cur_depth)
             m_traversal_stack_bool.resize(cur_depth+1);
-		if (m_traversal_stack.size() <= cur_depth) 
-				m_traversal_stack.resize(cur_depth+1);
+        if (m_traversal_stack.size() <= cur_depth) 
+                m_traversal_stack.resize(cur_depth+1);
 
-		if (m_manager.is_bool(ep))
-	        m_traversal_stack_bool[cur_depth].push_back(ep);
-		else
-		{
-	        m_traversal_stack[cur_depth].push_back(ep);
-			run_update_prune(cur_depth);
-		}
-		return run_update_bool_prune(cur_depth);
+        if (m_manager.is_bool(ep))
+            m_traversal_stack_bool[cur_depth].push_back(ep);
+        else
+        {
+            m_traversal_stack[cur_depth].push_back(ep);
+            run_update_prune(cur_depth);
+        }
+        return run_update_bool_prune(cur_depth);
     }
 #endif
 
-	void randomize_local(expr * e, unsigned int flip) {
+    void randomize_local(expr * e, unsigned int flip) {
         ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
 
         // Randomize _one_ candidate:
@@ -841,30 +841,30 @@ public:
         func_decl * fd = unsat_constants[r];
 #if _PERC_CHANGE_
         sort * srt = fd->get_range();
-		mpz temp;
+        mpz temp;
 
-		if (m_manager.is_bool(srt))
+        if (m_manager.is_bool(srt))
             m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
+        else
         {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+            mpz temp2, mask;
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(temp, m_tracker.get_value(fd));
 
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
+            for (unsigned bit = 0; bit < bv_sz; bit++)
+                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+                {
+                    m_mpz_manager.set(mask, m_powers(bit));
+                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
+                    m_mpz_manager.set(temp, temp2);
+                }
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(temp2);
+        }
 #else
-		mpz temp = m_tracker.get_random(fd->get_range());
+        mpz temp = m_tracker.get_random(fd->get_range());
 #endif
-		update(fd, temp);
+        update(fd, temp);
         m_mpz_manager.del(temp);
     } 
 
@@ -889,34 +889,34 @@ public:
         func_decl * fd = unsat_constants[r];
 #if _PERC_CHANGE_
         sort * srt = fd->get_range();
-		mpz temp;
+        mpz temp;
 
-		if (m_manager.is_bool(srt))
+        if (m_manager.is_bool(srt))
             m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
+        else
         {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+            mpz temp2, mask;
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(temp, m_tracker.get_value(fd));
 
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
+            for (unsigned bit = 0; bit < bv_sz; bit++)
+                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+                {
+                    m_mpz_manager.set(mask, m_powers(bit));
+                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
+                    m_mpz_manager.set(temp, temp2);
+                }
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(temp2);
+        }
 #else
-		mpz temp = m_tracker.get_random(fd->get_range());
+        mpz temp = m_tracker.get_random(fd->get_range());
 #endif
 
 #if _REAL_RS_ || _REAL_PBFS_
-		serious_update(fd, temp);
+        serious_update(fd, temp);
 #else
-		update(fd, temp);
+        update(fd, temp);
 #endif
         m_mpz_manager.del(temp);
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index a08588a51..553acc35a 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -125,10 +125,10 @@ Notes:
 
 
 #if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
-	InvalidConfiguration;
+    InvalidConfiguration;
 #endif
 #if (_PROBABILISTIC_UCT_ && !_UCT_)
-	InvalidConfiguration;
+    InvalidConfiguration;
 #endif
 
 
@@ -150,10 +150,10 @@ class sls_tactic : public tactic {
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
-			m_umins(0),
-			m_mul2s(0),
-			m_mul3s(0),
-			m_div2s(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -183,8 +183,8 @@ class sls_tactic : public tactic {
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
-		ptr_vector<mpz> m_old_values;
-		
+        ptr_vector<mpz> m_old_values;
+        
         typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
 
         imp(ast_manager & m, params_ref const & p, stats & s) : 
@@ -267,18 +267,18 @@ class sls_tactic : public tactic {
             #else
             double top_sum = 0.0;
             unsigned sz = g->size();
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
                 top_sum += m_tracker.get_score(e);
             }
 
-			TRACE("sls_top", tout << "Score distribution:"; 
+            TRACE("sls_top", tout << "Score distribution:"; 
                                     for (unsigned i = 0; i < sz; i++)
                                         tout << " " << m_tracker.get_score(g->form(i));
                                     tout << " AVG: " << top_sum / (double) sz << std::endl; );
 
 #if _CACHE_TOP_SCORE_
-			m_tracker.set_top_sum(top_sum);
+            m_tracker.set_top_sum(top_sum);
 #endif
 
             return top_sum / (double) sz;
@@ -292,20 +292,20 @@ class sls_tactic : public tactic {
         }
 
         double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.serious_update(fd, new_value);
+            m_evaluator.serious_update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
         }
 
         double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.update(fd, new_value);
+            m_evaluator.update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
@@ -314,18 +314,18 @@ class sls_tactic : public tactic {
 #if _EARLY_PRUNE_
         double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
             m_stats.m_incr_evals++;
-			if (m_evaluator.update_prune(fd, new_value))
+            if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-				return (m_tracker.get_top_sum() / g->size());
+                return (m_tracker.get_top_sum() / g->size());
 #else
-	            return top_score(g);
+                return top_score(g);
 #endif
-			else
-				return 0.0;
+            else
+                return 0.0;
         }
 #endif
 
-		// checks whether the score outcome of a given move is better than the previous score
+        // checks whether the score outcome of a given move is better than the previous score
         bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
 
@@ -357,11 +357,11 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// same as what_if, but only applied to the score of a specific atom, not the total score
+        // same as what_if, but only applied to the score of a specific atom, not the total score
         bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
             m_evaluator.update(fd, temp);
-			double r = m_tracker.get_score(e);
+            double r = m_tracker.get_score(e);
             if (r >= best_score) {
                 best_score = r;
                 best_const = fd_inx;            
@@ -378,29 +378,29 @@ class sls_tactic : public tactic {
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
 
-		}
+        }
 
-		// Andreas: do we really need all those temporary mpzs?
-		void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+        // Andreas: do we really need all those temporary mpzs?
+        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             mpz temp, mask, mask2;
             m_mpz_manager.mul(old_value, m_two, temp);
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
         }
 
         void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             m_mpz_manager.div(old_value, m_two, result);
         }
 
-		void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
             unsigned shift;        
             m_mpz_manager.add(old_value, m_one, incremented);
             if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
@@ -437,73 +437,73 @@ class sls_tactic : public tactic {
 
         void mk_random_move(goal_ref const & g) {
             unsigned rnd_mv = 0;
-			if (m_stats.m_moves > 10000)
-				rnd_mv = 0;
+            if (m_stats.m_moves > 10000)
+                rnd_mv = 0;
 
-			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
+            ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
 
-			mpz new_value;
+            mpz new_value;
 
-			sort * srt = fd->get_range();
+            sort * srt = fd->get_range();
             if (m_manager.is_bool(srt))
-				m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-			else
-			{
+                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+            else
+            {
 #if _USE_ADDSUB_
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-				move_type mt = (move_type) rnd_mv;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+                move_type mt = (move_type) rnd_mv;
 
-				// inversion doesn't make sense, let's do a flip instead.
-				if (mt == MV_INV) mt = MV_FLIP;
+                // inversion doesn't make sense, let's do a flip instead.
+                if (mt == MV_INV) mt = MV_FLIP;
 #else
-				mt = MV_FLIP;
+                mt = MV_FLIP;
 #endif
-				unsigned bit = 0;
+                unsigned bit = 0;
 
-				switch (mt)
-				{
-					case MV_FLIP: {
-					unsigned bv_sz = m_bv_util.get_bv_size(srt);
-					bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-					mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-					break;
-				}
-				case MV_INC: 
-					mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_DEC: 
-					mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_INV:
-					mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				default:
-					NOT_IMPLEMENTED_YET();
-				}
+                switch (mt)
+                {
+                    case MV_FLIP: {
+                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
+                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+                    break;
+                }
+                case MV_INC: 
+                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_DEC: 
+                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_INV:
+                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                default:
+                    NOT_IMPLEMENTED_YET();
+                }
 
-				TRACE("sls", tout << "Randomization candidates: ";
-							 for (unsigned i = 0; i < unsat_constants.size(); i++)
-								 tout << unsat_constants[i]->get_name() << ", ";
-							 tout << std::endl;
-							 tout << "Random move: ";
-							 switch (mt) {
-							 case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-							 case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-							 case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-							 case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-							 }
-							 tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-			}
+                TRACE("sls", tout << "Randomization candidates: ";
+                             for (unsigned i = 0; i < unsat_constants.size(); i++)
+                                 tout << unsat_constants[i]->get_name() << ", ";
+                             tout << std::endl;
+                             tout << "Random move: ";
+                             switch (mt) {
+                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+                             }
+                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+            }
 
-			m_evaluator.update(fd, new_value);            
-			m_mpz_manager.del(new_value);
-		}
+            m_evaluator.update(fd, new_value);            
+            m_mpz_manager.del(new_value);
+        }
 
-		// will use VNS to ignore some possible moves and increase the flips per second
+        // will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -514,7 +514,7 @@ class sls_tactic : public tactic {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
                 bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-				if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -536,12 +536,12 @@ class sls_tactic : public tactic {
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                         move = MV_INV;
 
-					// try to flip lsb
-					mk_flip(srt, old_value, 0, temp);                
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = 0;
-	                    move = MV_FLIP;
-					}
+                    // try to flip lsb
+                    mk_flip(srt, old_value, 0, temp);                
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = 0;
+                        move = MV_FLIP;
+                    }
                 }
 
                 // reset to what it was before
@@ -549,12 +549,12 @@ class sls_tactic : public tactic {
                 SASSERT(check == score);
             }
 
-			// we can either check the condition once in the beginning or check it repeatedly after every bit
+            // we can either check the condition once in the beginning or check it repeatedly after every bit
 #if _VNS_ == 1
-			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
 #else
-			if (new_score <= score)
-			for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+            if (new_score <= score)
+            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
 #endif
             for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
                 func_decl * fd = to_evaluate[i];
@@ -563,30 +563,30 @@ class sls_tactic : public tactic {
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 // What would happen if we flipped bit #j ?                
-				if (j < bv_sz)
-				{
-					mk_flip(srt, old_value, j, temp);                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);                
 
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = j;
-	                    move = MV_FLIP;
-	                }
-				}
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
                 SASSERT(check == score);
             }
-			m_mpz_manager.del(old_value);
+            m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
             return new_score;
         }        
 
-		// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
-			mpz temp2;
+            mpz temp2;
 #endif
             unsigned bv_sz;
             double new_score = score;
@@ -599,11 +599,11 @@ class sls_tactic : public tactic {
 
                 // first try to flip every bit
 #if _SKIP_BITS_
-				for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
 #else
-				for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
 #endif
-					// What would happen if we flipped bit #i ?                
+                    // What would happen if we flipped bit #i ?                
                     mk_flip(srt, old_value, j, temp);                
 
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
@@ -614,7 +614,7 @@ class sls_tactic : public tactic {
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
 #if _USE_ADDSUB_
-					if (!m_mpz_manager.is_even(old_value)) { 
+                    if (!m_mpz_manager.is_even(old_value)) { 
                         // for odd values, try +1
                         mk_inc(bv_sz, old_value, temp);
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
@@ -660,7 +660,7 @@ class sls_tactic : public tactic {
 
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
-				// Andreas: does not hold anymore now that we use top level score caching
+                // Andreas: does not hold anymore now that we use top level score caching
                 //SASSERT(check == score);
             }
 
@@ -669,17 +669,17 @@ class sls_tactic : public tactic {
 #if _USE_MUL3_
             m_mpz_manager.del(temp2);
 #endif
-			return new_score;
+            return new_score;
         }        
 
-		// same as find_best_move but only considers the score of the current expression instead of the overall score
-		double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+        // same as find_best_move but only considers the score of the current expression instead of the overall score
+        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
             unsigned bv_sz;
-			double new_score = m_tracker.get_score(e);
-			// Andreas: tie breaking not implemented yet
-			// double tie_score = top_score(g);
+            double new_score = m_tracker.get_score(e);
+            // Andreas: tie breaking not implemented yet
+            // double tie_score = top_score(g);
             for (unsigned i = 0; i < to_evaluate.size(); i++) {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
@@ -718,7 +718,7 @@ class sls_tactic : public tactic {
                 }
 
                 // reset to what it was before
-	            m_evaluator.update(fd, old_value);
+                m_evaluator.update(fd, old_value);
             }
 
             m_mpz_manager.del(old_value);
@@ -726,37 +726,37 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
-		// first try of intensification ... does not seem to be efficient
-		bool handle_plateau(goal_ref const & g)
-		{
-			unsigned sz = g->size();
+        // first try of intensification ... does not seem to be efficient
+        bool handle_plateau(goal_ref const & g)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned pos = m_stats.m_moves % sz;
+            unsigned pos = m_stats.m_moves % sz;
 #else
-			unsigned pos = m_tracker.get_random_uint(16) % sz;
+            unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-			{
-				m_tracker.get_value(to_evaluate[i]);
-				m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-			}            
-			unsigned new_const = (unsigned)-1, new_bit = 0;        
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+            {
+                m_tracker.get_value(to_evaluate[i]);
+                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+            }            
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
             mpz new_value;
             move_type move;
-			for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-			{
-				// Andreas: Could be extended to use (best) score but this is computationally more expensive.
+            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+            {
+                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
                 find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
 
                 if (new_const == static_cast<unsigned>(-1)) {
-					// Andreas: Actually this should never happen.
-					NOT_IMPLEMENTED_YET();
+                    // Andreas: Actually this should never happen.
+                    NOT_IMPLEMENTED_YET();
                 } else {
                     m_stats.m_moves++;
                     func_decl * fd = to_evaluate[new_const];
@@ -767,35 +767,35 @@ class sls_tactic : public tactic {
                     case MV_DEC: m_stats.m_decs++; break;
                     case MV_INV: m_stats.m_invs++; break;
                     case MV_UMIN: m_stats.m_umins++; break;
-					case MV_MUL2: m_stats.m_mul2s++; break;
-					case MV_MUL3: m_stats.m_mul3s++; break;
-					case MV_DIV2: m_stats.m_div2s++; break;
+                    case MV_MUL2: m_stats.m_mul2s++; break;
+                    case MV_MUL3: m_stats.m_mul3s++; break;
+                    case MV_DIV2: m_stats.m_div2s++; break;
                     }
                     
-					m_evaluator.update(fd, new_value);
+                    m_evaluator.update(fd, new_value);
                 }
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-				m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
 
-			m_old_values.reset();
+            m_old_values.reset();
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// what_if version needed in the context of 2nd intensification try, combining local and global score
+        // what_if version needed in the context of 2nd intensification try, combining local and global score
         bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
                         double & best_score, mpz & best_value, unsigned i) {
         
             double global_score = incremental_score(g, fd, temp);
-			double local_score = m_tracker.get_score(e);
+            double local_score = m_tracker.get_score(e);
             double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
-			if (new_score >= best_score) {
+            if (new_score >= best_score) {
                 best_score = new_score;
                 m_mpz_manager.set(best_value, temp);
                 return true;
@@ -804,17 +804,17 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// find_best_move version needed in the context of 2nd intensification try
+        // find_best_move version needed in the context of 2nd intensification try
         double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-		{
-			mpz old_value, temp;
+        {
+            mpz old_value, temp;
             double best_score = 0;
 
             sort * srt = fd->get_range();
             unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
             m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
-			for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
                 mk_flip(srt, old_value, j, temp);                
                 what_if(g, e, fd, temp, best_score, best_value, i); 
             }
@@ -822,54 +822,54 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
 
-			return best_score;
+            return best_score;
         }        
 
-		// second try to use intensification ... also not very effective
-		bool handle_plateau(goal_ref const & g, double old_score)
-		{
-			unsigned sz = g->size();
+        // second try to use intensification ... also not very effective
+        bool handle_plateau(goal_ref const & g, double old_score)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned new_const = m_stats.m_moves % sz;
+            unsigned new_const = m_stats.m_moves % sz;
 #else
-			unsigned new_const = m_tracker.get_random_uint(16) % sz;
+            unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
 
-			new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-			func_decl * fd = to_evaluate[new_const];
+            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+            func_decl * fd = to_evaluate[new_const];
 
-			mpz new_value;
-			//m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-			unsigned new_bit = 0;        
-			double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-			
-			for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-			{
+            mpz new_value;
+            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+            unsigned new_bit = 0;        
+            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+            
+            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+            {
                 new_score = find_best_move_local(g, q, fd, new_value, i);
 
                 m_stats.m_moves++;
                 m_stats.m_flips++;
 
-				global_score = incremental_score(g, fd, new_value);
-     			local_score = m_tracker.get_score(q);
+                global_score = incremental_score(g, fd, new_value);
+                 local_score = m_tracker.get_score(q);
 
-				SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// main search loop
-		lbool search(goal_ref const & g) {        
+        // main search loop
+        lbool search(goal_ref const & g) {        
             lbool res = l_undef;
             double score = 0.0, old_score = 0.0;
             unsigned new_const = (unsigned)-1, new_bit = 0;        
@@ -885,52 +885,52 @@ class sls_tactic : public tactic {
         
             unsigned plateau_cnt = 0;
 
-			// Andreas: Why do we only allow so few plateaus?
+            // Andreas: Why do we only allow so few plateaus?
 #if _RESTARTS_
-			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+            while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
-					if (m_stats.m_moves == 5590)
+                    if (m_stats.m_moves == 5590)
                     checkpoint();
 
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
 #endif
             
 #if _TYPE_RSTEP_
-					if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-					{
+                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                    {
 #if _TYPE_RSTEP_ == 1
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #elif _TYPE_RSTEP_ == 2
-						mk_random_move(g);
+                        mk_random_move(g);
 #endif
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
-							} else
-								TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-						}
-					}
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                            } else
+                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                        }
+                    }
 #endif
                     old_score = score;
                     new_const = (unsigned)-1;
                         
-					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-					if (!to_evaluate.size())
-					{
-						res = l_true;
-						goto bailout;
-					}
+                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+                    if (!to_evaluate.size())
+                    {
+                        res = l_true;
+                        goto bailout;
+                    }
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
@@ -952,11 +952,11 @@ class sls_tactic : public tactic {
                                         for (unsigned i = 0; i < g->size(); i++)
                                             tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
                                             m_tracker.get_score(g->form(i)) << std::endl; );
-						// Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                         score = old_score;
                     }
                     else {
-						// Andreas: Why does randomizing not count as a move? (Now it does.)
+                        // Andreas: Why does randomizing not count as a move? (Now it does.)
                         m_stats.m_moves++;
                         func_decl * fd = to_evaluate[new_const];
 
@@ -984,15 +984,15 @@ class sls_tactic : public tactic {
                         case MV_DEC: m_stats.m_decs++; break;
                         case MV_INV: m_stats.m_invs++; break;
                         case MV_UMIN: m_stats.m_umins++; break;
-						case MV_MUL2: m_stats.m_mul2s++; break;
-						case MV_MUL3: m_stats.m_mul3s++; break;
-						case MV_DIV2: m_stats.m_div2s++; break;
+                        case MV_MUL2: m_stats.m_mul2s++; break;
+                        case MV_MUL3: m_stats.m_mul3s++; break;
+                        case MV_DIV2: m_stats.m_div2s++; break;
                         }
                     
 #if _REAL_RS_ || _REAL_PBFS_
-						score = serious_score(g, fd, new_value);
+                        score = serious_score(g, fd, new_value);
 #else
-						score = incremental_score(g, fd, new_value);    
+                        score = incremental_score(g, fd, new_value);    
 #endif
 
                         TRACE("sls", tout << "Score distribution:"; 
@@ -1004,7 +1004,7 @@ class sls_tactic : public tactic {
                     if (score >= 0.99999) {
 //                    if (score >= 1.0) {
                         // score could theoretically be imprecise.
-						// Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -1015,43 +1015,43 @@ class sls_tactic : public tactic {
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
-					/*
-					if (m_stats.m_moves % 100 == 0)
-					{
-						verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-						verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-					}*/
+                    /*
+                    if (m_stats.m_moves % 100 == 0)
+                    {
+                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+                    }*/
                 }
                 while (score > old_score && res == l_undef);                
-				
-				// Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                
+                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
                 if (score != old_score) {
-					report_tactic_progress("This should not happen I guess.", plateau_cnt);
+                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
                     plateau_cnt = 0;
-				} else {
-					m_stats.m_moves++;
+                } else {
+                    m_stats.m_moves++;
                     plateau_cnt++;
-					//report_tactic_progress("Plateau.", plateau_cnt);
-					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //report_tactic_progress("Plateau.", plateau_cnt);
+                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
                     //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
 #if _INTENSIFICATION_
-						handle_plateau(g, score);
-						//handle_plateau(g);
+                        handle_plateau(g, score);
+                        //handle_plateau(g);
 #else
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #endif
-						//mk_random_move(g);
+                        //mk_random_move(g);
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
@@ -1070,43 +1070,43 @@ class sls_tactic : public tactic {
                 return;
             }
 
-			verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-			verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-			verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-			verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-			verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-			verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-			verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-			verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-			verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-			verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-			verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-			verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-			verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-			verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-			verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-			verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-			verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-			verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-			verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-			verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-			verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-			verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-			verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-			
+            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+            
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
 #endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
             do {
                 checkpoint();
-				// Andreas: I think restarts are too impotant to ignore 99% of them are happening...
+                // Andreas: I think restarts are too impotant to ignore 99% of them are happening...
                 //if ((m_stats.m_restarts % 100) == 0)                        
                     report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 
@@ -1115,12 +1115,12 @@ class sls_tactic : public tactic {
                 if (res == l_undef)
                     m_tracker.randomize();
             }
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
-			verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
 
             if (res == l_true) {    
-				report_tactic_progress("Number of flips:", m_stats.m_moves);
+                report_tactic_progress("Number of flips:", m_stats.m_moves);
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -1254,7 +1254,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
+                        // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index b26912e5c..006bbb888 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -29,31 +29,31 @@ class sls_tracker {
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
     mpz                   m_zero, m_one, m_two;
-	    
+        
     struct value_score { 
 #if _EARLY_PRUNE_
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
 #else
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
 #endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
 #if _EARLY_PRUNE_
-		double score_prune;
-		unsigned has_pos_occ;
-		unsigned has_neg_occ;
+        double score_prune;
+        unsigned has_pos_occ;
+        unsigned has_neg_occ;
 #endif
         unsigned distance; // max distance from any root
-		unsigned touched;
+        unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
-			touched = other.touched;
+            touched = other.touched;
             return *this;
         }
     };
@@ -72,18 +72,18 @@ private:
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
 #if _UCT_
-	unsigned              m_touched;
+    unsigned              m_touched;
 #endif
 #if _REAL_RS_ || _REAL_PBFS_
-	ptr_vector<expr>	  m_unsat_expr;
-	obj_map<expr, unsigned>	m_where_false;
-	expr**					m_list_false;
+    ptr_vector<expr>      m_unsat_expr;
+    obj_map<expr, unsigned>    m_where_false;
+    expr**                    m_list_false;
 #endif
 #if _CACHE_TOP_SCORE_
-	double				  m_top_sum;
+    double                  m_top_sum;
 #endif
 #if _WEIGHT_DIST_ == 4
-	double				  m_weight_dist_factor;
+    double                  m_weight_dist_factor;
 #endif
 
 public:    
@@ -105,23 +105,23 @@ public:
     }
 
 #if _WEIGHT_DIST_ == 4
-	inline void set_weight_dist_factor(double val) {
-		m_weight_dist_factor = val;
-	}
+    inline void set_weight_dist_factor(double val) {
+        m_weight_dist_factor = val;
+    }
 #endif
 
 #if _CACHE_TOP_SCORE_
-	inline void adapt_top_sum(double add, double sub) {
-		m_top_sum += add - sub;
-	}
+    inline void adapt_top_sum(double add, double sub) {
+        m_top_sum += add - sub;
+    }
 
-	inline void set_top_sum(double new_score) {
-		m_top_sum = new_score;
-	}
+    inline void set_top_sum(double new_score) {
+        m_top_sum = new_score;
+    }
 
-	inline double get_top_sum() {
-		return m_top_sum;
-	}
+    inline double get_top_sum() {
+        return m_top_sum;
+    }
 #endif
 
     inline void set_value(expr * n, const mpz & r) {
@@ -174,20 +174,20 @@ public:
         m_scores.find(n).score_prune = score;
     }
 
-	inline double & get_score_prune(expr * n) {
+    inline double & get_score_prune(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).score_prune;
     }
 
-	inline unsigned has_pos_occ(expr * n) {
+    inline unsigned has_pos_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_pos_occ;
- 	}
+     }
 
-	inline unsigned has_neg_occ(expr * n) {
+    inline unsigned has_neg_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
- 	}
+     }
 #endif
 
     inline unsigned get_distance(expr * n) {
@@ -316,45 +316,45 @@ public:
         }
     }
 
-	void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(proc, visited, q);
-			}
-		}
-		for_each_expr(proc, visited, e);
- 	}
+    void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(proc, visited, q);
+            }
+        }
+        for_each_expr(proc, visited, e);
+     }
 
-	void initialize_recursive(expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(q);
-			}
-		}
-		ptr_vector<func_decl> t;
+    void initialize_recursive(expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(q);
+            }
+        }
+        ptr_vector<func_decl> t;
         m_constants_occ.insert_if_not_there(e, t);
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
- 	}
+     }
 
-	void initialize(goal_ref const & g) {
+    void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2
-			initialize_recursive(proc, visited, e);
+            initialize_recursive(proc, visited, e);
 #endif
             for_each_expr(proc, visited, e);
         }
@@ -363,9 +363,9 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
-			initialize_recursive(e);
+            initialize_recursive(e);
 #endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
@@ -379,53 +379,53 @@ public:
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
 #if _REAL_RS_ || _REAL_PBFS_
-		m_list_false = new expr*[sz];
+        m_list_false = new expr*[sz];
         for (unsigned i = 0; i < sz; i++)
-	  		if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-				break_assertion(g->form(i));
+              if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+                break_assertion(g->form(i));
 #endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-	  		setup_occs(g->form(i));
+              setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-		m_touched = 1;
+        m_touched = 1;
 #endif
     }
 
 #if _REAL_RS_ || _REAL_PBFS_
-	void make_assertion(expr * e)
-	{
-		if (m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.find(e);
-			m_where_false.erase(e);
-			if (pos != m_where_false.size())
-			{
-				expr * q = m_list_false[m_where_false.size()];
-				m_list_false[pos] = q;
-				m_where_false.find(q) = pos;
-			}
-//			printf("Going in %d\n", m_where_false.size());
-		}
-		//if (m_unsat_expr.contains(e))
-			//m_unsat_expr.erase(e);
-	}
+    void make_assertion(expr * e)
+    {
+        if (m_where_false.contains(e))
+        {
+            unsigned pos = m_where_false.find(e);
+            m_where_false.erase(e);
+            if (pos != m_where_false.size())
+            {
+                expr * q = m_list_false[m_where_false.size()];
+                m_list_false[pos] = q;
+                m_where_false.find(q) = pos;
+            }
+//            printf("Going in %d\n", m_where_false.size());
+        }
+        //if (m_unsat_expr.contains(e))
+            //m_unsat_expr.erase(e);
+    }
 
-	void break_assertion(expr * e)
-	{
-		if (!m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.size();
-			m_list_false[pos] = e;
-			m_where_false.insert(e, pos);
-	//		printf("Going in %d\n", m_where_false.size());
-		}
-		//if (!m_unsat_expr.contains(e))
-			//m_unsat_expr.push_back(e);
-	}
+    void break_assertion(expr * e)
+    {
+        if (!m_where_false.contains(e))
+        {
+            unsigned pos = m_where_false.size();
+            m_list_false[pos] = e;
+            m_where_false.insert(e, pos);
+    //        printf("Going in %d\n", m_where_false.size());
+        }
+        //if (!m_unsat_expr.contains(e))
+            //m_unsat_expr.push_back(e);
+    }
 #endif
 
     void show_model(std::ostream & out) {
@@ -537,35 +537,35 @@ public:
     }              
 
 #if _EARLY_PRUNE_
-	void setup_occs(expr * n, bool negated = false) {
-		if (m_manager.is_bool(n))
-		{
-			if (m_manager.is_and(n) || m_manager.is_or(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            expr * const * args = a->get_args();
-	            for (unsigned i = 0; i < a->get_num_args(); i++)
-					setup_occs(args[i]);
-			}
-			else if (m_manager.is_not(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            SASSERT(a->get_num_args() == 1);
-	            expr * child = a->get_arg(0);
-	            if (m_manager.is_and(child) || m_manager.is_or(child))
-	                NOT_IMPLEMENTED_YET();
-				setup_occs(child, true);
-			}
-			else
-			{
-				if (negated)
-					m_scores.find(n).has_neg_occ = 1;
-				else
-					m_scores.find(n).has_pos_occ = 1;
-			}
-		}
+    void setup_occs(expr * n, bool negated = false) {
+        if (m_manager.is_bool(n))
+        {
+            if (m_manager.is_and(n) || m_manager.is_or(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                expr * const * args = a->get_args();
+                for (unsigned i = 0; i < a->get_num_args(); i++)
+                    setup_occs(args[i]);
+            }
+            else if (m_manager.is_not(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                SASSERT(a->get_num_args() == 1);
+                expr * child = a->get_arg(0);
+                if (m_manager.is_and(child) || m_manager.is_or(child))
+                    NOT_IMPLEMENTED_YET();
+                setup_occs(child, true);
+            }
+            else
+            {
+                if (negated)
+                    m_scores.find(n).has_neg_occ = 1;
+                else
+                    m_scores.find(n).has_pos_occ = 1;
+            }
+        }
         else
             NOT_IMPLEMENTED_YET();
     }
@@ -574,7 +574,7 @@ public:
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
-		double res = 0.0;
+        double res = 0.0;
             
         if (is_uninterp_const(n)) {
             const mpz & r = get_value(n);
@@ -587,14 +587,14 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it does not even occur.
+            // Andreas: Seems to have no effect. Probably it does not even occur.
 #if _SCORE_AND_AVG_
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
                 sum += get_score(args[i]);
             res = sum / (double) a->get_num_args();
 #else
-			double min = 1.0;
+            double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur < min) min = cur;
@@ -606,16 +606,16 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it is still too similar to the original version.
+            // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
 #if _SCORE_OR_MUL_
-			double inv = 1.0;
+            double inv = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 inv *= (1.0 - get_score(args[i]));
             }
             res = 1.0 - inv;
 #else
-			double max = 0.0;
+            double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur > max) max = cur;
@@ -639,7 +639,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-			
+            
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -701,7 +701,7 @@ public:
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
                     res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-					m_mpz_manager.del(diff);
+                    m_mpz_manager.del(diff);
                 }
             }
             else {
@@ -762,7 +762,7 @@ public:
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
-			m_mpz_manager.del(x);
+            m_mpz_manager.del(x);
             m_mpz_manager.del(y);                
         }
         else if (m_manager.is_not(n)) {                
@@ -797,25 +797,25 @@ public:
         SASSERT(res >= 0.0 && res <= 1.0);
 
 #if _WEIGHT_DIST_
-		app * a = to_app(n);
-		family_id afid = a->get_family_id();
+        app * a = to_app(n);
+        family_id afid = a->get_family_id();
 
-		if (afid == m_bv_util.get_family_id())
+        if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
-		if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+        if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
 #elif _WEIGHT_DIST_ == 2
-		res *= res;
+        res *= res;
 #elif _WEIGHT_DIST_ == 3
-		if (res < 1.0) res = 0.0;
+        if (res < 1.0) res = 0.0;
 #elif _WEIGHT_DIST_ == 4
-		if (res < 1.0) res *= m_weight_dist_factor;
+        if (res < 1.0) res *= m_weight_dist_factor;
 #endif
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-	
+    
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -861,34 +861,34 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-	expr * get_unsat_expression(expr * e) {
-		if (m_manager.is_bool(e)) {
-			if (m_manager.is_and(e) || m_manager.is_or(e)) {
-				app * a = to_app(e);
-				expr * const * args = a->get_args();
-			    // Andreas: might be used for guided branching
-				//for (unsigned i = 0; i < a->get_num_args(); i++) {
-					//double cur = get_score(args[i]);
-				//}
-				// Andreas: A random number is better here since reusing flip will cause patterns.
-				unsigned int sz = a->get_num_args();
-				unsigned int pos = get_random_uint(16) % sz;
-				for (unsigned int i = pos; i < sz; i++) {
-	                expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-				}
-				for (unsigned int i = 0; i < pos; i++) {
-					expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-	            }
-	        }
-		}
-		return e;
-	}
+    expr * get_unsat_expression(expr * e) {
+        if (m_manager.is_bool(e)) {
+            if (m_manager.is_and(e) || m_manager.is_or(e)) {
+                app * a = to_app(e);
+                expr * const * args = a->get_args();
+                // Andreas: might be used for guided branching
+                //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                    //double cur = get_score(args[i]);
+                //}
+                // Andreas: A random number is better here since reusing flip will cause patterns.
+                unsigned int sz = a->get_num_args();
+                unsigned int pos = get_random_uint(16) % sz;
+                for (unsigned int i = pos; i < sz; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+                for (unsigned int i = 0; i < pos; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+            }
+        }
+        return e;
+    }
 
-	ptr_vector<func_decl> & get_constants(expr * e) {
+    ptr_vector<func_decl> & get_constants(expr * e) {
         ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
         unsigned sz = this_decls.size();
         for (unsigned i = 0; i < sz; i++) {
@@ -897,9 +897,9 @@ public:
                 m_temp_constants.push_back(fd);
         }
         return m_temp_constants;
-	}
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
@@ -913,244 +913,244 @@ public:
             }
         }
         return m_temp_constants;
-	}
+    }
 
-	expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
-			for (unsigned i = pos; i < sz; i++) {
+    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+            for (unsigned i = pos; i < sz; i++) {
                 expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
-			}
-			for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
+                    return q;
             }
-			return 0;
-	}
+            for (unsigned i = 0; i < pos; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+                    return q;
+            }
+            return 0;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-			expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(g, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
-			if (!q)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            if (!q)
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
-			if (!e)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
+            if (!e)
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz = this_decls.size();
             for (unsigned j = 0; j < sz; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & go_deeper(expr * e) {
-			if (m_manager.is_bool(e)) {
-				if (m_manager.is_and(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-				    // Andreas: might be used for guided branching
-					//for (unsigned i = 0; i < a->get_num_args(); i++) {
-						//double cur = get_score(args[i]);
-					//}
-					// Andreas: A random number is better here since reusing flip will cause patterns.
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-				else if (m_manager.is_or(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-			}
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & go_deeper(expr * e) {
+            if (m_manager.is_bool(e)) {
+                if (m_manager.is_and(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    // Andreas: might be used for guided branching
+                    //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                        //double cur = get_score(args[i]);
+                    //}
+                    // Andreas: A random number is better here since reusing flip will cause patterns.
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+                else if (m_manager.is_or(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+            }
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-		expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(g, sz, pos);
         if (!q)
-			return m_temp_constants;
+            return m_temp_constants;
 
-		return go_deeper(q);
-	}
+        return go_deeper(q);
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
-			if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
-				return m_temp_constants;
-			else
-	            return get_constants();
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+                return m_temp_constants;
+            else
+                return get_constants();
         }
         else {
             m_temp_constants.reset();
 #if _FOCUS_ == 1
 #if _UCT_
-			unsigned pos = -1;
-			value_score vscore;
+            unsigned pos = -1;
+            value_score vscore;
 #if _PROBABILISTIC_UCT_
-			double sum_score = 0.0;
-			unsigned start_index = get_random_uint(16) % sz;
-			for (unsigned i = start_index; i < sz; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+            double sum_score = 0.0;
+            unsigned start_index = get_random_uint(16) % sz;
+            for (unsigned i = start_index; i < sz; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
-			for (unsigned i = 0; i < start_index; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }    
+            }
+            for (unsigned i = 0; i < start_index; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }    
+            }
 #else
-			double max = -1.0;
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+            double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
 #if _UCT_ == 1
-				double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
 #elif _UCT_ == 2
-				double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+                double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
 #endif
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
 
 #if _UCT_ == 1
-			m_scores.find(g->form(pos)).touched++;
-			m_touched++;
+            m_scores.find(g->form(pos)).touched++;
+            m_touched++;
 #elif _UCT_ == 2
-			m_scores.find(g->form(pos)).touched = flip; 
+            m_scores.find(g->form(pos)).touched = flip; 
 #endif
-			expr * e = g->form(pos);
+            expr * e = g->form(pos);
 
 #elif _BFS_ == 3
-			unsigned int pos = -1;
-			double max = -1.0;
+            unsigned int pos = -1;
+            double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 2
-			unsigned int pos = -1;
-			double min = 2.0;
+            unsigned int pos = -1;
+            double min = 2.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+                if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 1
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #elif _UNIFORM_RANDOM_
-			unsigned cnt_unsat = 0, pos = -1;
-			for (unsigned i = 0; i < sz; i++)
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            unsigned cnt_unsat = 0, pos = -1;
+            for (unsigned i = 0; i < sz; i++)
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;    
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _REAL_RS_
-			//unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[get_random_uint(16) % sz];
+            //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            else
+                expr * e = m_list_false[get_random_uint(16) % sz];
 #elif _REAL_PBFS_
-			//unsigned pos = m_false_list[flip % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[flip % sz];
+            //unsigned pos = m_false_list[flip % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            else
+                expr * e = m_list_false[flip % sz];
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #endif
-			return get_unsat_constants_walksat(e);
+            return get_unsat_constants_walksat(e);
 #elif _FOCUS_ == 2
 #if _BFS_
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
 #endif
-			return get_unsat_constants_crsat(g, sz, pos);
+            return get_unsat_constants_crsat(g, sz, pos);
 #else
-			return get_unsat_constants_gsat(g, sz);
+            return get_unsat_constants_gsat(g, sz);
 #endif
         }
     }

From aa6f8a4b8a1cb68933b420f053b487971dfb2d28 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Wed, 19 Mar 2014 11:49:44 +0000
Subject: [PATCH 038/108] Current version for relocating.

---
 src/tactic/sls/sls_evaluator.h |  92 +++++-----
 src/tactic/sls/sls_tactic.cpp  | 295 +++++++++++++++++++++++++++---
 src/tactic/sls/sls_tracker.h   | 315 ++++++++++++++++++++++++++++++---
 3 files changed, 600 insertions(+), 102 deletions(-)

diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index cdb08038f..696d7664a 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -78,7 +78,11 @@ public:
             case OP_AND: {
                 m_mpz_manager.set(result, m_one);
                 for (unsigned i = 0; i < n_args; i++)
+#if _DIRTY_UP_
+                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i]))  {
+#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result))  {
+#endif
                         m_mpz_manager.set(result, m_zero);
                         break;
                     }
@@ -86,7 +90,11 @@ public:
             }
             case OP_OR: {
                 for (unsigned i = 0; i < n_args; i++)
+#if _DIRTY_UP_
+                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i]))  {
+#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) {
+#endif
                         m_mpz_manager.set(result, m_one);
                         break;
                     }
@@ -94,9 +102,16 @@ public:
             }
             case OP_NOT: {
                 SASSERT(n_args == 1);
+#if _DIRTY_UP_
+                if (m_tracker.is_top_expr(args[0]))
+                    m_mpz_manager.set(result, m_zero);
+                else
+                    m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero);
+#else
                 const mpz & child = m_tracker.get_value(args[0]);
                 SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child));                
-                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);                
+                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);
+#endif
                 break;
             }
             case OP_EQ: {
@@ -542,7 +557,8 @@ public:
                 m_tracker.set_value(cur, new_value);
 
 #if _REAL_RS_ || _REAL_PBFS_
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                 {
                     if (m_mpz_manager.eq(new_value,m_one))
                         m_tracker.make_assertion(cur);
@@ -554,7 +570,8 @@ public:
 #if _EARLY_PRUNE_
                 new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
@@ -562,13 +579,14 @@ public:
 #else
 #if _CACHE_TOP_SCORE_
                 new_score = m_tracker.score(cur);
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif            
+#endif			
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -611,7 +629,8 @@ public:
 #if _EARLY_PRUNE_
                 new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
@@ -619,13 +638,14 @@ public:
 #else
 #if _CACHE_TOP_SCORE_
                 new_score = m_tracker.score(cur);
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif            
+#endif			
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -695,7 +715,7 @@ public:
 
         double prune_score, new_score;
         unsigned pot_benefits = 0;
-         SASSERT(cur_depth < m_traversal_stack_bool.size());
+        SASSERT(cur_depth < m_traversal_stack_bool.size());
  
         ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
 
@@ -704,7 +724,8 @@ public:
 
             new_score = m_tracker.score(cur); 
 #if _CACHE_TOP_SCORE_
-            if (!m_tracker.has_uplinks(cur))
+            //if (!m_tracker.has_uplinks(cur))
+            if (m_tracker.is_top_expr(cur))
                 m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
             prune_score = m_tracker.get_score_prune(cur);
@@ -745,7 +766,8 @@ public:
 
 #if _CACHE_TOP_SCORE_
                     new_score = m_tracker.score(cur); 
-                    if (!m_tracker.has_uplinks(cur))
+                    //if (!m_tracker.has_uplinks(cur))
+                    if (m_tracker.is_top_expr(cur))
                         m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
 #else
@@ -833,44 +855,7 @@ public:
     }
 #endif
 
-    void randomize_local(expr * e, unsigned int flip) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
-
-        // Randomize _one_ candidate:
-        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
-        func_decl * fd = unsat_constants[r];
-#if _PERC_CHANGE_
-        sort * srt = fd->get_range();
-        mpz temp;
-
-        if (m_manager.is_bool(srt))
-            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-        else
-        {
-            mpz temp2, mask;
-            unsigned bv_sz = m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(temp, m_tracker.get_value(fd));
-
-            for (unsigned bit = 0; bit < bv_sz; bit++)
-                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-                {
-                    m_mpz_manager.set(mask, m_powers(bit));
-                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
-                    m_mpz_manager.set(temp, temp2);
-                }
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(temp2);
-        }
-#else
-        mpz temp = m_tracker.get_random(fd->get_range());
-#endif
-        update(fd, temp);
-        m_mpz_manager.del(temp);
-    } 
-
-     void randomize_local(goal_ref const & g, unsigned int flip) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
-
+    void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _all_ candidates:
 
         //// bool did_something = false;
@@ -927,6 +912,15 @@ public:
                         tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
                         tout << "Locally randomized model: " << std::endl; 
                         m_tracker.show_model(tout); );
+
+    }
+
+    void randomize_local(expr * e) {
+        randomize_local(m_tracker.get_constants(e));
+    } 
+
+     void randomize_local(goal_ref const & g, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(g, flip));
     } 
 };
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 553acc35a..ada0ec359 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -34,6 +34,8 @@ Notes:
 #include"propagate_values_tactic.h"
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
+#include"luby.h"
+#include "ctx_simplify_tactic.h"
 
 // which unsatisfied assertion is selected? only works with _FOCUS_ > 0
 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
@@ -43,9 +45,23 @@ Notes:
 // 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
 #define _FOCUS_ 1
 
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 0
+
 // do we use restarts?
-// 0 = no, otherwise the value defines the maximum number of moves
-#define _RESTARTS_ 0
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 3.0
 
 // timelimit
 #define _TIMELIMIT_ 3600
@@ -66,38 +82,58 @@ Notes:
 // 2 = yes, by squaring it
 // 3 = yes, by setting it to zero
 // 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 0
+#define _WEIGHT_DIST_ 1
 
 // the factor used for _WEIGHT_DIST_ = 1
 #define _WEIGHT_DIST_FACTOR_ 0.25
 
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
 // do we use intensification steps in local minima? if so, how many?
 #define _INTENSIFICATION_ 0
 #define _INTENSIFICATION_TRIES_ 0
 
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 0
+#define _UCT_ 1
 
 // how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 0.01
+#define _UCT_CONSTANT_ 10.0
 
 // is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
 #define _PROBABILISTIC_UCT_ 0
 
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 1
+
 // shall we use addition/subtraction?
 #define _USE_ADDSUB_ 1
 
 // shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 1
+#define _USE_MUL2DIV2_ 0
 
 // shall we try multiplication by 3?
-#define _USE_MUL3_ 1
+#define _USE_MUL3_ 0
 
 // shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 1
+#define _USE_UNARY_MINUS_ 0
 
 // is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 1
+#define _UNIFORM_RANDOM_ 0
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
@@ -124,13 +160,21 @@ Notes:
 #define _CACHE_TOP_SCORE_ 1
 
 
-#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
     InvalidConfiguration;
 #endif
 #if (_PROBABILISTIC_UCT_ && !_UCT_)
     InvalidConfiguration;
 #endif
-
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+    InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+    InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+    InvalidConfiguration;
+#endif
 
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
@@ -180,6 +224,7 @@ class sls_tactic : public tactic {
         sls_tracker     m_tracker;
         sls_evaluator   m_evaluator;
 
+        unsigned		m_restart_limit;
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
@@ -208,6 +253,41 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(m_two);
         }        
 
+        double get_restart_armin(unsigned cnt_restarts)
+        {
+            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+            //printf("armin: %f\n", pow(1.1, inner_id + 1));
+            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
+        }
+
+        inline unsigned check_restart(unsigned curr_value)
+        {
+            if (curr_value > m_restart_limit)
+            {
+#if _RESTART_SCHEME_ == 4
+                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+#elif _RESTART_SCHEME_ == 3
+                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 2
+                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 1
+                if (m_stats.m_restarts & 1)
+                    m_restart_limit += _RESTART_LIMIT_;
+                else
+                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+#else
+                    m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
+                return 0;
+            }
+            return 1;
+        }
+
         ast_manager & m() const { return m_manager; }
 
         void set_cancel(bool f) { m_cancel = f; }
@@ -435,12 +515,10 @@ class sls_tactic : public tactic {
                 NOT_IMPLEMENTED_YET();
         }
 
-        void mk_random_move(goal_ref const & g) {
+        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
+        {
             unsigned rnd_mv = 0;
-            if (m_stats.m_moves > 10000)
-                rnd_mv = 0;
 
-            ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
@@ -503,6 +581,10 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(new_value);
         }
 
+        void mk_random_move(goal_ref const & g) {
+            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
+        }
+
         // will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
@@ -857,7 +939,7 @@ class sls_tactic : public tactic {
                 m_stats.m_flips++;
 
                 global_score = incremental_score(g, fd, new_value);
-                 local_score = m_tracker.get_score(q);
+                local_score = m_tracker.get_score(q);
 
                 SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
 
@@ -875,6 +957,130 @@ class sls_tactic : public tactic {
             unsigned new_const = (unsigned)-1, new_bit = 0;        
             mpz new_value;
             move_type move;
+            unsigned plateau_cnt = 0;
+
+            score = rescore(g);
+            unsigned sz = g->size();
+#if _PERC_STICKY_
+            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+
+#if _RESTARTS_ == 1
+            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 2
+            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 3
+            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
+                checkpoint();
+                m_stats.m_moves++;
+
+#if _REAL_RS_ || _REAL_PBFS_
+                //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
+
+#if _FOCUS_
+#if _PERC_STICKY_
+                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#else
+                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+                if (!e)
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+                if (!to_evaluate.size())
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+#endif
+
+#if _TYPE_RSTEP_
+                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                {
+#if _TYPE_RSTEP_ == 1
+                    m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
+                    mk_random_move(to_evaluate);
+#endif
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                }
+                continue;
+#endif
+
+#if _WEIGHT_DIST_ == 4
+                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
+                old_score = score;
+                new_const = (unsigned)-1;
+
+#if _VNS_
+                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+
+                if (new_const == static_cast<unsigned>(-1)) {
+                    score = old_score;
+                    plateau_cnt++;
+#if _INTENSIFICATION_
+                    handle_plateau(g, score);
+                    //handle_plateau(g);
+                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                        mk_random_move(to_evaluate);
+                    else
+#endif
+#if _REPICK_
+                    m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
+                    m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
+
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                } else {
+                    func_decl * fd = to_evaluate[new_const];              
+#if _REAL_RS_ || _REAL_PBFS_
+                    score = serious_score(g, fd, new_value);
+#else
+                    score = incremental_score(g, fd, new_value);    
+#endif
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        // main search loop
+        lbool search_old(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
             
             score = rescore(g);
             TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
@@ -887,12 +1093,12 @@ class sls_tactic : public tactic {
 
             // Andreas: Why do we only allow so few plateaus?
 #if _RESTARTS_
-            while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
             while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
-                    if (m_stats.m_moves == 5590)
                     checkpoint();
 
 #if _WEIGHT_DIST_ == 4
@@ -1072,7 +1278,11 @@ class sls_tactic : public tactic {
 
             verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
             verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
             verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
             verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
             verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
             verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
@@ -1081,9 +1291,14 @@ class sls_tactic : public tactic {
             verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
             verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
             verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
             verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
             verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
             verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
             verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
             verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
             verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
@@ -1099,21 +1314,30 @@ class sls_tactic : public tactic {
             verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
             
 #if _WEIGHT_DIST_ == 4
-                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
 #endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
+            m_restart_limit = _RESTART_LIMIT_;
+
             do {
                 checkpoint();
-                // Andreas: I think restarts are too impotant to ignore 99% of them are happening...
-                //if ((m_stats.m_restarts % 100) == 0)                        
-                    report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                
+
+                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 res = search(g);
 
                 if (res == l_undef)
-                    m_tracker.randomize();
+                {
+#if _RESTART_INIT_
+                    m_tracker.randomize(g);
+#else
+                    m_tracker.reset(g);
+#endif
+                }
             }
             while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
@@ -1121,6 +1345,13 @@ class sls_tactic : public tactic {
 
             if (res == l_true) {    
                 report_tactic_progress("Number of flips:", m_stats.m_moves);
+                for (unsigned i = 0; i < g->size(); i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                    {
+                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                        NOT_IMPLEMENTED_YET(); 
+                    }
+
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -1183,12 +1414,17 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = alloc(imp, m, m_params, m_stats);
+        imp * d = m_imp;
         #pragma omp critical (tactic_cancel)
         {
-            std::swap(d, m_imp);
+            d = m_imp;
         }
         dealloc(d);
+        d = alloc(imp, m, m_params, m_stats);
+        #pragma omp critical (tactic_cancel) 
+        {
+            m_imp = d;
+        }
     }
     
     virtual void collect_statistics(statistics & st) const {
@@ -1246,6 +1482,9 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
     // conservative gaussian elimination. 
     gaussian_p.set_uint("gaussian_max_occs", 2); 
 
+    params_ref ctx_p;
+    ctx_p.set_uint("max_depth", 32);
+    ctx_p.set_uint("max_steps", 5000000);
     return and_then(and_then(mk_simplify_tactic(m),                             
                              mk_propagate_values_tactic(m),
                              using_params(mk_solve_eqs_tactic(m), gaussian_p),
@@ -1254,6 +1493,10 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
+                        // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
+                        //mk_ctx_simplify_tactic(m, ctx_p),
+                        // Andreas: This one at least eliminates top level duplicates ...
+                        mk_simplify_tactic(m),
                         // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 006bbb888..0aca1f59c 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -65,6 +65,7 @@ private:
     typedef obj_map<expr, value_score> scores_type;    
     typedef obj_map<expr, ptr_vector<expr> > uplinks_type;    
     typedef obj_map<expr, ptr_vector<func_decl> > occ_type;
+    obj_hashtable<expr>	  m_top_expr;
     scores_type           m_scores;
     uplinks_type          m_uplinks;
     entry_point_type      m_entry_points;
@@ -75,15 +76,15 @@ private:
     unsigned              m_touched;
 #endif
 #if _REAL_RS_ || _REAL_PBFS_
-    ptr_vector<expr>      m_unsat_expr;
-    obj_map<expr, unsigned>    m_where_false;
-    expr**                    m_list_false;
+    ptr_vector<expr>	  m_unsat_expr;
+    obj_map<expr, unsigned>	m_where_false;
+    expr**					m_list_false;
 #endif
 #if _CACHE_TOP_SCORE_
-    double                  m_top_sum;
+    double				  m_top_sum;
 #endif
-#if _WEIGHT_DIST_ == 4
-    double                  m_weight_dist_factor;
+#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
+    double				  m_weight_dist_factor;
 #endif
 
 public:    
@@ -104,7 +105,7 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
-#if _WEIGHT_DIST_ == 4
+#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     inline void set_weight_dist_factor(double val) {
         m_weight_dist_factor = val;
     }
@@ -182,12 +183,12 @@ public:
     inline unsigned has_pos_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_pos_occ;
-     }
+    }
 
     inline unsigned has_neg_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
-     }
+    }
 #endif
 
     inline unsigned get_distance(expr * n) {
@@ -213,11 +214,62 @@ public:
         return m_uplinks.contains(n);
     }
 
+    inline bool is_top_expr(expr * n) {
+        return m_top_expr.contains(n);
+    }
+
     inline ptr_vector<expr> & get_uplinks(expr * n) {
         SASSERT(m_uplinks.contains(n));
         return m_uplinks.find(n);
     }
 
+#if _REAL_RS_ || _REAL_PBFS_
+    void debug_real(goal_ref const & g, unsigned flip)
+    {
+        unsigned count = 0;
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            expr * e = g->form(i);
+            if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e))
+            {
+                printf("iteration %d: ", flip);
+                printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size());
+                exit(4);
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e))
+            {
+                printf("iteration %d: ", flip);
+                printf("form %d is unsat but not in unsat list\n", i);
+                exit(4);
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e))
+            {
+                unsigned pos = m_where_false.find(e);
+                expr * q = m_list_false[pos];
+                if (q != e)
+                {
+                    printf("iteration %d: ", flip);
+                    printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos);
+                    exit(4);
+                }
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero))
+                count++;
+        }
+
+        // should be true now that duplicate assertions are removed
+        if (count != m_where_false.size())
+        {
+                printf("iteration %d: ", flip);
+                printf("%d are unsat but list is of size %d\n", count, m_where_false.size());
+                exit(4);
+        }
+    }
+#endif
+
     void initialize(app * n) {
         // Build score table
         if (!m_scores.contains(n)) {
@@ -327,7 +379,7 @@ public:
             }
         }
         for_each_expr(proc, visited, e);
-     }
+    }
 
     void initialize_recursive(expr * e) {
         if (m_manager.is_and(e) || m_manager.is_or(e)) {
@@ -344,7 +396,7 @@ public:
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
-     }
+    }
 
     void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
@@ -352,6 +404,10 @@ public:
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
+            if (!m_top_expr.contains(e))
+                m_top_expr.insert(e);
+            else
+                printf("this is already in ...\n");
             // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2
             initialize_recursive(proc, visited, e);
@@ -380,18 +436,20 @@ public:
 
 #if _REAL_RS_ || _REAL_PBFS_
         m_list_false = new expr*[sz];
-        for (unsigned i = 0; i < sz; i++)
-              if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-                break_assertion(g->form(i));
+        //for (unsigned i = 0; i < sz; i++)
+        //{
+        //	if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+        //		break_assertion(g->form(i));
+        //}
 #endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-              setup_occs(g->form(i));
+            setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-        m_touched = 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
 #endif
     }
 
@@ -407,8 +465,12 @@ public:
                 expr * q = m_list_false[m_where_false.size()];
                 m_list_false[pos] = q;
                 m_where_false.find(q) = pos;
+                //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos);
             }
-//            printf("Going in %d\n", m_where_false.size());
+            //else
+                //printf("Erasing %d from %d to %d\n", e, pos);
+//			m_list_false[m_where_false.size()] = 0;
+//			printf("Going in %d\n", m_where_false.size());
         }
         //if (m_unsat_expr.contains(e))
             //m_unsat_expr.erase(e);
@@ -416,12 +478,14 @@ public:
 
     void break_assertion(expr * e)
     {
+        //printf("I'm broken... that's still fine.\n");
         if (!m_where_false.contains(e))
         {
+            //printf("This however is not so cool...\n");
             unsigned pos = m_where_false.size();
             m_list_false[pos] = e;
             m_where_false.insert(e, pos);
-    //        printf("Going in %d\n", m_where_false.size());
+    //		printf("Going in %d\n", m_where_false.size());
         }
         //if (!m_unsat_expr.contains(e))
             //m_unsat_expr.push_back(e);
@@ -522,7 +586,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize() {
+    void randomize(goal_ref const & g) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -534,6 +598,28 @@ public:
         }
 
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
+
+#if _UCT_RESET_
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
+#endif
+    }              
+
+    void reset(goal_ref const & g) {
+        TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
+
+        for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
+            mpz temp = m_zero;
+            set_value(it->m_value, temp);
+            m_mpz_manager.del(temp);
+        }
+
+#if _UCT_RESET_
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
+#endif
     }              
 
 #if _EARLY_PRUNE_
@@ -591,12 +677,20 @@ public:
 #if _SCORE_AND_AVG_
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
+#if _DIRTY_UP_
+                sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 sum += get_score(args[i]);
+#endif
             res = sum / (double) a->get_num_args();
 #else
             double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 if (cur < min) min = cur;
             }
             res = min;
@@ -610,14 +704,22 @@ public:
 #if _SCORE_OR_MUL_
             double inv = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 inv *= (1.0 - get_score(args[i]));
             }
             res = 1.0 - inv;
 #else
             double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 if (cur > max) max = cur;
             }
             res = max;
@@ -772,7 +874,11 @@ public:
             expr * child = a->get_arg(0);
             if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
                 NOT_IMPLEMENTED_YET();
+#if _DIRTY_UP_
+            res = is_top_expr(child) ? 0.0 : score_bool(child, true);
+#else
             res = score_bool(child, true);
+#endif
         }
         else if (m_manager.is_distinct(n)) {
             app * a = to_app(n);
@@ -803,7 +909,11 @@ public:
         if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
+#if _WEIGHT_TOGGLE_
+        if (res < 1.0) res *= m_weight_dist_factor;
+#else
         if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+#endif
 #elif _WEIGHT_DIST_ == 2
         res *= res;
 #elif _WEIGHT_DIST_ == 3
@@ -900,6 +1010,10 @@ public:
     }
 
     ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+        if (sz == 1)
+            return get_constants();
+        m_temp_constants.reset();
+
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
@@ -945,7 +1059,7 @@ public:
     }
 
     ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
-            if (!e)
+            if (!e || m_temp_constants.size())
                 return m_temp_constants;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz = this_decls.size();
@@ -1033,32 +1147,43 @@ public:
 #if _PROBABILISTIC_UCT_
             double sum_score = 0.0;
             unsigned start_index = get_random_uint(16) % sz;
+            
             for (unsigned i = start_index; i < sz; i++)
             {
                 expr * e = g->form(i);
                 vscore = m_scores.find(e);
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#if _PROBABILISTIC_UCT_ == 2
+                double q = vscore.score * vscore.score; 
+#else
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
                 if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
                     sum_score += q;
                     if (rand() <= (q * RAND_MAX / sum_score) + 1)
                         pos = i;
-                }    
+                }	
             }
             for (unsigned i = 0; i < start_index; i++)
             {
                 expr * e = g->form(i);
                 vscore = m_scores.find(e);
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#if _PROBABILISTIC_UCT_ == 2
+                double q = vscore.score * vscore.score; 
+#else
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
                 if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
                     sum_score += q;
                     if (rand() <= (q * RAND_MAX / sum_score) + 1)
                         pos = i;
-                }    
+                }	
             }
 #else
             double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
                 expr * e = g->form(i);
+//            for (unsigned i = 0; i < m_where_false.size(); i++) {
+//                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
@@ -1078,6 +1203,7 @@ public:
             m_scores.find(g->form(pos)).touched = flip; 
 #endif
             expr * e = g->form(pos);
+//            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
             unsigned int pos = -1;
@@ -1109,7 +1235,7 @@ public:
 #elif _UNIFORM_RANDOM_
             unsigned cnt_unsat = 0, pos = -1;
             for (unsigned i = 0; i < sz; i++)
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;    
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
             if (pos == static_cast<unsigned>(-1))
                 return m_temp_constants;
             expr * e = g->form(pos);
@@ -1120,8 +1246,7 @@ public:
             sz = m_where_false.size();
             if (sz == 0)
                 return m_temp_constants;
-            else
-                expr * e = m_list_false[get_random_uint(16) % sz];
+            expr * e = m_list_false[get_random_uint(16) % sz];
 #elif _REAL_PBFS_
             //unsigned pos = m_false_list[flip % m_cnt_false];
             //expr * e = get_unsat_assertion(g, sz, pos);
@@ -1154,6 +1279,142 @@ public:
 #endif
         }
     }
+    
+
+    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
+
+        if (sz == 1)
+            return g->form(0);
+
+        m_temp_constants.reset();
+#if _FOCUS_ == 1
+#if _UCT_
+        unsigned pos = -1;
+        value_score vscore;
+#if _PROBABILISTIC_UCT_
+        double sum_score = 0.0;
+        unsigned start_index = get_random_uint(16) % sz;
+            
+        for (unsigned i = start_index; i < sz; i++)
+        {
+            expr * e = g->form(i);
+            vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+            double q = vscore.score * vscore.score + _UCT_EPS_; 
+#else
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                sum_score += q;
+                if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                    pos = i;
+            }	
+        }
+        for (unsigned i = 0; i < start_index; i++)
+        {
+            expr * e = g->form(i);
+            vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+            double q = vscore.score * vscore.score + _UCT_EPS_; 
+#else
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                sum_score += q;
+                if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                    pos = i;
+            }	
+        }
+#else
+        double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+//            for (unsigned i = 0; i < m_where_false.size(); i++) {
+//                expr * e = m_list_false[i];
+                vscore = m_scores.find(e);
+#if _UCT_ == 1
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#elif _UCT_ == 2
+            double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#endif
+            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+            }
+#endif
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+
+#if _UCT_ == 1
+        m_scores.find(g->form(pos)).touched++;
+        m_touched++;
+#elif _UCT_ == 2
+        m_scores.find(g->form(pos)).touched = flip; 
+#endif
+//        return m_list_false[pos];
+        return g->form(pos);
+
+#elif _BFS_ == 3
+        unsigned int pos = -1;
+        double max = -1.0;
+        for (unsigned i = 0; i < sz; i++) {
+            expr * e = g->form(i);
+               double q = get_score(e);
+            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _BFS_ == 2
+        unsigned int pos = -1;
+        double min = 2.0;
+        for (unsigned i = 0; i < sz; i++) {
+            expr * e = g->form(i);
+               double q = get_score(e);
+            if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+        }
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _BFS_ == 1
+        unsigned int pos = flip % sz;
+        return get_unsat_assertion(g, sz, pos);
+#elif _UNIFORM_RANDOM_
+        unsigned cnt_unsat = 0, pos = -1;
+        for (unsigned i = 0; i < sz; i++)
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _REAL_RS_
+        //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+        //expr * e = get_unsat_assertion(g, sz, pos);
+        //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+        sz = m_where_false.size();
+        if (sz == 0)
+            return 0;
+        return m_list_false[get_random_uint(16) % sz];
+#elif _REAL_PBFS_
+        //unsigned pos = m_false_list[flip % m_cnt_false];
+        //expr * e = get_unsat_assertion(g, sz, pos);
+        //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+        sz = m_where_false.size();
+        if (sz == 0)
+            return0;
+        else
+            return m_list_false[flip % sz];
+#else
+        unsigned int pos = get_random_uint(16) % sz;
+        return get_unsat_assertion(g, sz, pos);
+#endif
+        return g->form(pos);
+#elif _FOCUS_ == 2
+#if _BFS_
+        unsigned int pos = flip % sz;
+#else
+        unsigned int pos = get_random_uint(16) % sz;
+#endif
+        return get_unsat_constants_crsat(g, sz, pos);
+#endif
+    }
 };
 
 #endif
\ No newline at end of file

From b1eeb9adf409da3188f0380a0b7280e5d6a428eb Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 17:04:38 +0000
Subject: [PATCH 039/108] SLS refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h |  158 +++
 src/tactic/sls/sls_engine.cpp             | 1160 +++++++++++++++++
 src/tactic/sls/sls_engine.h               |  159 +++
 src/tactic/sls/sls_evaluator.h            |    3 +
 src/tactic/sls/sls_tactic.cpp             | 1397 +--------------------
 src/tactic/sls/sls_tracker.h              |   10 +-
 6 files changed, 1520 insertions(+), 1367 deletions(-)
 create mode 100644 src/tactic/sls/sls_compilation_settings.h
 create mode 100644 src/tactic/sls/sls_engine.cpp
 create mode 100644 src/tactic/sls/sls_engine.h

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
new file mode 100644
index 000000000..aea4787b0
--- /dev/null
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -0,0 +1,158 @@
+/*++
+Copyright (c) 2014 Microsoft Corporation
+
+Module Name:
+
+    sls_compilation_constants.h
+
+Abstract:
+
+    Stochastic Local Search (SLS) compilation constants
+
+Author:
+
+    Christoph (cwinter) 2014-03-19
+
+Notes:
+
+    This file should go away completely once we have evaluated all options.
+
+--*/
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
+#define _FOCUS_ 1
+
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 0
+
+// do we use restarts?
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 3.0
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
+#define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
+#define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
+#define _VNS_ 0
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 1
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.25
+
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 1
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 10.0
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
+#define _PROBABILISTIC_UCT_ 0
+
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 1
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 0
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 0
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 0
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 0
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
+InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+InvalidConfiguration;
+#endif
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+InvalidConfiguration;
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
new file mode 100644
index 000000000..92471aad8
--- /dev/null
+++ b/src/tactic/sls/sls_engine.cpp
@@ -0,0 +1,1160 @@
+/*++
+Copyright (c) 2012 Microsoft Corporation
+
+Module Name:
+
+    sls_engine.cpp
+
+Abstract:
+
+    A Stochastic Local Search (SLS) engine
+
+Author:
+
+    Christoph (cwinter) 2014-03-19
+
+Notes:
+
+--*/
+#include<iomanip>
+
+#include"map.h"
+#include"ast_smt2_pp.h"
+#include"ast_pp.h"
+#include"var_subst.h"
+#include"model_pp.h"
+#include"tactic.h"
+#include"cooperate.h"
+#include"luby.h"
+
+#include"sls_compilation_settings.h"
+#include"sls_params.hpp"
+#include"sls_engine.h"
+
+
+sls_engine::sls_engine(ast_manager & m, params_ref const & p) :
+    m_manager(m),    
+    m_powers(m_mpz_manager),
+    m_zero(m_mpz_manager.mk_z(0)),
+    m_one(m_mpz_manager.mk_z(1)),
+    m_two(m_mpz_manager.mk_z(2)),
+    m_cancel(false),
+    m_bv_util(m),
+    m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
+    m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers)
+{
+    updt_params(p);
+}
+
+sls_engine::~sls_engine() {
+    m_mpz_manager.del(m_zero);
+    m_mpz_manager.del(m_one);
+    m_mpz_manager.del(m_two);
+}
+
+double sls_engine::get_restart_armin(unsigned cnt_restarts)
+{
+    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+    //printf("armin: %f\n", pow(1.1, inner_id + 1));
+    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
+}    
+
+void sls_engine::updt_params(params_ref const & _p) {
+    sls_params p(_p);
+    m_produce_models = _p.get_bool("model", false);
+    m_max_restarts = p.restarts();
+    m_tracker.set_random_seed(p.random_seed());
+    m_plateau_limit = p.plateau_limit();
+}
+
+void sls_engine::checkpoint() {
+    if (m_cancel)
+        throw tactic_exception(TACTIC_CANCELED_MSG);
+    cooperate("sls");
+}
+
+bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
+    bool res = true;
+
+    unsigned sz = g->size();
+    for (unsigned i = 0; i < sz && res; i++) {
+        checkpoint();
+        expr_ref o(m_manager);
+
+        if (!mdl.eval(g->form(i), o, true))
+            exit(ERR_INTERNAL_FATAL);
+
+        res = m_manager.is_true(o.get());
+    }
+
+    TRACE("sls", tout << "Evaluation: " << res << std::endl;);
+
+    return res;
+}
+
+double sls_engine::top_score(goal_ref const & g) {
+#if 0
+    double min = m_tracker.get_score(g->form(0));
+    unsigned sz = g->size();
+    for (unsigned i = 1; i < sz; i++) {
+        double q = m_tracker.get_score(g->form(i));
+        if (q < min) min = q;
+    }
+    TRACE("sls_top", tout << "Score distribution:";
+    for (unsigned i = 0; i < sz; i++)
+        tout << " " << m_tracker.get_score(g->form(i));
+    tout << " MIN: " << min << std::endl;);
+    return min;
+#else
+    double top_sum = 0.0;
+    unsigned sz = g->size();
+    for (unsigned i = 0; i < sz; i++) {
+        expr * e = g->form(i);
+        top_sum += m_tracker.get_score(e);
+    }
+
+    TRACE("sls_top", tout << "Score distribution:";
+    for (unsigned i = 0; i < sz; i++)
+        tout << " " << m_tracker.get_score(g->form(i));
+    tout << " AVG: " << top_sum / (double)sz << std::endl;);
+
+#if _CACHE_TOP_SCORE_
+    m_tracker.set_top_sum(top_sum);
+#endif
+
+    return top_sum / (double)sz;
+#endif
+}
+
+double sls_engine::rescore(goal_ref const & g) {
+    m_evaluator.update_all();
+    m_stats.m_full_evals++;
+    return top_score(g);
+}
+
+double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+    m_evaluator.serious_update(fd, new_value);
+    m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+    return (m_tracker.get_top_sum() / g->size());
+#else
+    return top_score(g);
+#endif
+}
+
+double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+    m_evaluator.update(fd, new_value);
+    m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+    return (m_tracker.get_top_sum() / g->size());
+#else
+    return top_score(g);
+#endif
+}
+
+double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+#if _EARLY_PRUNE_
+    m_stats.m_incr_evals++;
+    if (m_evaluator.update_prune(fd, new_value))
+#if _CACHE_TOP_SCORE_
+        return (m_tracker.get_top_sum() / g->size());
+#else
+        return top_score(g);
+#endif
+    else
+        return 0.0;
+#else
+    NOT_IMPLEMENTED_YET();
+#endif
+}
+
+// checks whether the score outcome of a given move is better than the previous score
+bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
+
+#ifdef Z3DEBUG
+    mpz old_value;
+    m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+#endif
+
+#if _EARLY_PRUNE_
+    double r = incremental_score_prune(g, fd, temp);
+#else
+    double r = incremental_score(g, fd, temp);
+#endif   
+#ifdef Z3DEBUG
+    TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
+            " --> " << r << std::endl;);
+
+    m_mpz_manager.del(old_value);
+#endif
+
+    //            if (r >= best_score) {
+    if (r > best_score) {
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
+// same as what_if, but only applied to the score of a specific atom, not the total score
+bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                    double & best_score, unsigned & best_const, mpz & best_value) {
+    m_evaluator.update(fd, temp);
+    double r = m_tracker.get_score(e);
+    if (r >= best_score) {
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
+void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
+    mpz temp, mask, mask2;
+    m_mpz_manager.add(old_value, add_value, temp);
+    m_mpz_manager.set(mask, m_powers(bv_sz));
+    m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+    m_mpz_manager.bitwise_and(temp, mask2, result);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(mask);
+    m_mpz_manager.del(mask2);
+
+}
+
+// Andreas: do we really need all those temporary mpzs?
+void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+    mpz temp, mask, mask2;
+    m_mpz_manager.mul(old_value, m_two, temp);
+    m_mpz_manager.set(mask, m_powers(bv_sz));
+    m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+    m_mpz_manager.bitwise_and(temp, mask2, result);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(mask);
+    m_mpz_manager.del(mask2);
+}
+
+void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+    m_mpz_manager.div(old_value, m_two, result);
+}
+
+void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+    unsigned shift;
+    m_mpz_manager.add(old_value, m_one, incremented);
+    if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
+        m_mpz_manager.set(incremented, m_zero);
+}
+
+void sls_engine::mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
+    if (m_mpz_manager.is_zero(old_value)) {
+        m_mpz_manager.set(decremented, m_powers(bv_sz));
+        m_mpz_manager.dec(decremented);
+    }
+    else
+        m_mpz_manager.sub(old_value, m_one, decremented);
+}
+
+void sls_engine::mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
+    m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
+}
+
+void sls_engine::mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
+    m_mpz_manager.set(flipped, m_zero);
+
+    if (m_bv_util.is_bv_sort(s)) {
+        mpz mask;
+        m_mpz_manager.set(mask, m_powers(bit));
+        m_mpz_manager.bitwise_xor(old_value, mask, flipped);
+        m_mpz_manager.del(mask);
+    }
+    else if (m_manager.is_bool(s))
+        m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
+    else
+        NOT_IMPLEMENTED_YET();
+}
+
+void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
+{
+    unsigned rnd_mv = 0;
+    unsigned ucc = unsat_constants.size();
+    unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
+    func_decl * fd = unsat_constants[rc];
+
+    mpz new_value;
+
+    sort * srt = fd->get_range();
+    if (m_manager.is_bool(srt))
+        m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+    else
+    {
+#if _USE_ADDSUB_
+        if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
+        if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+        move_type mt = (move_type)rnd_mv;
+
+        // inversion doesn't make sense, let's do a flip instead.
+        if (mt == MV_INV) mt = MV_FLIP;
+#else
+        mt = MV_FLIP;
+#endif
+        unsigned bit = 0;
+
+        switch (mt)
+        {
+        case MV_FLIP: {
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+            mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+            break;
+        }
+        case MV_INC:
+            mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+            break;
+        case MV_DEC:
+            mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+            break;
+        case MV_INV:
+            mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+            break;
+        default:
+            NOT_IMPLEMENTED_YET();
+        }
+
+        TRACE("sls", tout << "Randomization candidates: ";
+        for (unsigned i = 0; i < unsat_constants.size(); i++)
+            tout << unsat_constants[i]->get_name() << ", ";
+        tout << std::endl;
+        tout << "Random move: ";
+        switch (mt) {
+        case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+        case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+        case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+        case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+        }
+        tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout););
+    }
+
+    m_evaluator.update(fd, new_value);
+    m_mpz_manager.del(new_value);
+}
+
+void sls_engine::mk_random_move(goal_ref const & g) {
+    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
+}
+
+// will use VNS to ignore some possible moves and increase the flips per second
+double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+    unsigned bv_sz, max_bv_sz = 0;
+    double new_score = score;
+
+    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+            // try to flip lsb
+            mk_flip(srt, old_value, 0, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = 0;
+                move = MV_FLIP;
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        SASSERT(check == score);
+    }
+
+    // we can either check the condition once in the beginning or check it repeatedly after every bit
+#if _VNS_ == 1
+    for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+    if (new_score <= score)
+        for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
+// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+    mpz temp2;
+#endif
+    unsigned bv_sz;
+    double new_score = score;
+
+    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        // first try to flip every bit
+#if _SKIP_BITS_
+        for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
+#else
+        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+            // What would happen if we flipped bit #i ?                
+            mk_flip(srt, old_value, j, temp);
+
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = j;
+                move = MV_FLIP;
+            }
+        }
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+#if _USE_ADDSUB_
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+#endif
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+            mk_inc(bv_sz, temp, temp2);
+            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+            // try multiplication by 2
+            mk_mul2(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_MUL2;
+
+#if _USE_MUL3_
+            // try multiplication by 3
+            mk_add(bv_sz, old_value, temp, temp2);
+            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                move = MV_MUL3;
+#endif
+
+            // try division by 2
+            mk_div2(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_DIV2;
+#endif
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        // Andreas: does not hold anymore now that we use top level score caching
+        //SASSERT(check == score);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+#if _USE_MUL3_
+    m_mpz_manager.del(temp2);
+#endif
+    return new_score;
+}
+
+// same as find_best_move but only considers the score of the current expression instead of the overall score
+double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+    unsigned bv_sz;
+    double new_score = m_tracker.get_score(e);
+    // Andreas: tie breaking not implemented yet
+    // double tie_score = top_score(g);
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        // first try to flip every bit
+        for (unsigned j = 0; j < bv_sz; j++) {
+            // What would happen if we flipped bit #i ?                
+            mk_flip(srt, old_value, j, temp);
+
+            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = j;
+                move = MV_FLIP;
+            }
+        }
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+        }
+
+        // reset to what it was before
+        m_evaluator.update(fd, old_value);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
+// first try of intensification ... does not seem to be efficient
+bool sls_engine::handle_plateau(goal_ref const & g)
+{
+    unsigned sz = g->size();
+#if _BFS_
+    unsigned pos = m_stats.m_moves % sz;
+#else
+    unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+    if (!e)
+        return 0;
+
+    expr * q = m_tracker.get_unsat_expression(e);
+    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+    for (unsigned i = 0; i < to_evaluate.size(); i++)
+    {
+        m_tracker.get_value(to_evaluate[i]);
+        m_old_values.push_back(&m_tracker.get_value(to_evaluate[i]));
+    }
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+    for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+    {
+        // Andreas: Could be extended to use (best) score but this is computationally more expensive.
+        find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
+
+        if (new_const == static_cast<unsigned>(-1)) {
+            // Andreas: Actually this should never happen.
+            NOT_IMPLEMENTED_YET();
+        }
+        else {
+            m_stats.m_moves++;
+            func_decl * fd = to_evaluate[new_const];
+
+            switch (move) {
+            case MV_FLIP: m_stats.m_flips++; break;
+            case MV_INC: m_stats.m_incs++; break;
+            case MV_DEC: m_stats.m_decs++; break;
+            case MV_INV: m_stats.m_invs++; break;
+            case MV_UMIN: m_stats.m_umins++; break;
+            case MV_MUL2: m_stats.m_mul2s++; break;
+            case MV_MUL3: m_stats.m_mul3s++; break;
+            case MV_DIV2: m_stats.m_div2s++; break;
+            }
+
+            m_evaluator.update(fd, new_value);
+        }
+
+        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+            return 1;
+    }
+
+    for (unsigned i = 0; i < to_evaluate.size(); i++)
+        m_tracker.set_value(to_evaluate[i], *m_old_values[i]);
+
+    m_old_values.reset();
+
+    return 0;
+}
+
+// what_if version needed in the context of 2nd intensification try, combining local and global score
+bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                double & best_score, mpz & best_value, unsigned i) {
+
+    double global_score = incremental_score(g, fd, temp);
+    double local_score = m_tracker.get_score(e);
+    double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+    if (new_score >= best_score) {
+        best_score = new_score;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
+// find_best_move version needed in the context of 2nd intensification try
+double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+{
+    mpz old_value, temp;
+    double best_score = 0;
+
+    sort * srt = fd->get_range();
+    unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+    m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+    for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+        mk_flip(srt, old_value, j, temp);
+        what_if(g, e, fd, temp, best_score, best_value, i);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+
+    return best_score;
+}
+
+// second try to use intensification ... also not very effective
+bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
+{
+    unsigned sz = g->size();
+#if _BFS_
+    unsigned new_const = m_stats.m_moves % sz;
+#else
+    unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+    if (!e)
+        return 0;
+
+    expr * q = m_tracker.get_unsat_expression(e);
+    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+    new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+    func_decl * fd = to_evaluate[new_const];
+
+    mpz new_value;
+    //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+    unsigned new_bit = 0;
+    double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+
+    for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+    {
+        new_score = find_best_move_local(g, q, fd, new_value, i);
+
+        m_stats.m_moves++;
+        m_stats.m_flips++;
+
+        global_score = incremental_score(g, fd, new_value);
+        local_score = m_tracker.get_score(q);
+
+        SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+            return 1;
+    }
+
+    return 0;
+}
+
+// main search loop
+lbool sls_engine::search(goal_ref const & g) {
+    lbool res = l_undef;
+    double score = 0.0, old_score = 0.0;
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+    unsigned plateau_cnt = 0;
+
+    score = rescore(g);
+    unsigned sz = g->size();
+#if _PERC_STICKY_
+    expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#endif
+
+#if _RESTARTS_ == 1
+    while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#elif _RESTARTS_ == 2
+    while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#elif _RESTARTS_ == 3
+    while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#else
+    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#endif
+        checkpoint();
+        m_stats.m_moves++;
+
+#if _REAL_RS_ || _REAL_PBFS_
+        //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
+
+#if _FOCUS_
+#if _PERC_STICKY_
+        if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+            e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#else
+        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#endif
+        if (!e)
+        {
+            res = l_true;
+            goto bailout;
+        }
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+        if (!to_evaluate.size())
+        {
+            res = l_true;
+            goto bailout;
+        }
+#endif
+
+#if _TYPE_RSTEP_
+        if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+        {
+#if _TYPE_RSTEP_ == 1
+            m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
+            mk_random_move(to_evaluate);
+#endif
+#if _CACHE_TOP_SCORE_
+            score = m_tracker.get_top_sum() / g->size();
+#else
+            score = top_score(g);
+#endif
+        }
+        continue;
+#endif
+
+#if _WEIGHT_DIST_ == 4
+        m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
+        old_score = score;
+        new_const = (unsigned)-1;
+
+#if _VNS_
+        score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+
+        if (new_const == static_cast<unsigned>(-1)) {
+            score = old_score;
+            plateau_cnt++;
+#if _INTENSIFICATION_
+            handle_plateau(g, score);
+            //handle_plateau(g);
+            //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+            //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+            if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                mk_random_move(to_evaluate);
+            else
+#endif
+#if _REPICK_
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
+                m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
+
+#if _CACHE_TOP_SCORE_
+            score = m_tracker.get_top_sum() / g->size();
+#else
+            score = top_score(g);
+#endif
+        }
+        else {
+            func_decl * fd = to_evaluate[new_const];
+#if _REAL_RS_ || _REAL_PBFS_
+            score = serious_score(g, fd, new_value);
+#else
+            score = incremental_score(g, fd, new_value);
+#endif
+        }
+    }
+
+bailout:
+    m_mpz_manager.del(new_value);
+
+    return res;
+}
+
+// main search loop
+lbool sls_engine::search_old(goal_ref const & g) {
+    lbool res = l_undef;
+    double score = 0.0, old_score = 0.0;
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+
+    score = rescore(g);
+    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+    tout << "Score distribution:";
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    tout << " TOP: " << score << std::endl;);
+
+    unsigned plateau_cnt = 0;
+
+    // Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+    while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+        //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {
+#endif
+        do {
+            checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+
+#if _TYPE_RSTEP_
+            if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+            {
+#if _TYPE_RSTEP_ == 1
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+                mk_random_move(g);
+#endif
+                score = top_score(g);
+
+                if (score >= 1.0) {
+                    bool all_true = true;
+                    for (unsigned i = 0; i < g->size() && all_true; i++)
+                        if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                            all_true = false;
+                    if (all_true) {
+                        res = l_true; // sat
+                        goto bailout;
+                    }
+                    else
+                        TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                }
+            }
+#endif
+            old_score = score;
+            new_const = (unsigned)-1;
+
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+            if (!to_evaluate.size())
+            {
+                res = l_true;
+                goto bailout;
+            }
+            TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                tout << to_evaluate[i]->get_name() << std::endl;);
+
+#if _VNS_
+            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+            if (new_const == static_cast<unsigned>(-1)) {
+                TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
+                for (unsigned i = 0; i < g->size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                });
+
+                TRACE("sls_max", m_tracker.show_model(tout);
+                tout << "Scores: " << std::endl;
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
+                    m_tracker.get_score(g->form(i)) << std::endl;);
+                // Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                score = old_score;
+            }
+            else {
+                // Andreas: Why does randomizing not count as a move? (Now it does.)
+                m_stats.m_moves++;
+                func_decl * fd = to_evaluate[new_const];
+
+                TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
+                switch (move) {
+                case MV_FLIP:
+                    tout << "Flip";
+                    if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
+                    break;
+                case MV_INC:
+                    tout << "+1";
+                    break;
+                case MV_DEC:
+                    tout << "-1";
+                    break;
+                case MV_INV:
+                    tout << "NEG";
+                    break;
+                };
+                tout << ") ; new score = " << std::setprecision(32) << score << std::endl;);
+
+                switch (move) {
+                case MV_FLIP: m_stats.m_flips++; break;
+                case MV_INC: m_stats.m_incs++; break;
+                case MV_DEC: m_stats.m_decs++; break;
+                case MV_INV: m_stats.m_invs++; break;
+                case MV_UMIN: m_stats.m_umins++; break;
+                case MV_MUL2: m_stats.m_mul2s++; break;
+                case MV_MUL3: m_stats.m_mul3s++; break;
+                case MV_DIV2: m_stats.m_div2s++; break;
+                }
+
+#if _REAL_RS_ || _REAL_PBFS_
+                score = serious_score(g, fd, new_value);
+#else
+                score = incremental_score(g, fd, new_value);
+#endif
+
+                TRACE("sls", tout << "Score distribution:";
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                tout << " TOP: " << score << std::endl;);
+            }
+
+            if (score >= 0.99999) {
+                //                    if (score >= 1.0) {
+                // score could theoretically be imprecise.
+                // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                bool all_true = true;
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        all_true = false;
+                if (all_true) {
+                    res = l_true; // sat
+                    goto bailout;
+                }
+                else
+                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+            }
+            /*
+            if (m_stats.m_moves % 100 == 0)
+            {
+            verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+            verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+            }*/
+        } while (score > old_score && res == l_undef);
+
+        // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+        if (score != old_score) {
+            report_tactic_progress("This should not happen I guess.", plateau_cnt);
+            plateau_cnt = 0;
+        }
+        else {
+            m_stats.m_moves++;
+            plateau_cnt++;
+            //report_tactic_progress("Plateau.", plateau_cnt);
+            // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+            //if (plateau_cnt < m_plateau_limit) {
+            TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
+#if _INTENSIFICATION_
+            handle_plateau(g, score);
+            //handle_plateau(g);
+#else
+            m_evaluator.randomize_local(g, m_stats.m_moves);
+#endif
+            //mk_random_move(g);
+            score = top_score(g);
+
+            if (score >= 1.0) {
+                bool all_true = true;
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        all_true = false;
+                if (all_true) {
+                    res = l_true; // sat
+                    goto bailout;
+                }
+                else
+                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+            }
+        }
+    }
+
+bailout:
+    m_mpz_manager.del(new_value);
+
+    return res;
+}
+
+void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
+    if (g->inconsistent()) {
+        mc = 0;
+        return;
+    }
+
+    m_produce_models = g->models_enabled();
+
+    verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+    verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+    verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
+    verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+    verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+    verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+    verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
+    verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+    verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+    verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+    verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+    verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+    verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+    verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+    verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+    verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+    verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
+    verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+    verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+    verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+    verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+    verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+    verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+    verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+    verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+    verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+    verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+    verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+    verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+    verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+    verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+    verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+    verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+    verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+    verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(g);
+    lbool res = l_undef;
+
+    m_restart_limit = _RESTART_LIMIT_;
+
+    do {
+        checkpoint();
+
+        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+        res = search(g);
+
+        if (res == l_undef)
+        {
+#if _RESTART_INIT_
+            m_tracker.randomize(g);
+#else
+            m_tracker.reset(g);
+#endif
+        }
+    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+
+    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+
+    if (res == l_true) {
+        report_tactic_progress("Number of flips:", m_stats.m_moves);
+        for (unsigned i = 0; i < g->size(); i++)
+            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+            {
+                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                NOT_IMPLEMENTED_YET();
+            }
+
+        if (m_produce_models) {
+            model_ref mdl = m_tracker.get_model();
+            mc = model2model_converter(mdl.get());
+            TRACE("sls_model", mc->display(tout););
+        }
+        g->reset();
+    }
+    else
+        mc = 0;
+}
+
+unsigned sls_engine::check_restart(unsigned curr_value)
+{
+    if (curr_value > m_restart_limit)
+    {
+#if _RESTART_SCHEME_ == 4
+        m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+#elif _RESTART_SCHEME_ == 3
+        m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 2
+        m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 1
+        if (m_stats.m_restarts & 1)
+            m_restart_limit += _RESTART_LIMIT_;
+        else
+            m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+#else
+        m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+        printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+        m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
+        return 0;
+    }
+    return 1;
+}
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
new file mode 100644
index 000000000..878354c6d
--- /dev/null
+++ b/src/tactic/sls/sls_engine.h
@@ -0,0 +1,159 @@
+/*++
+Copyright (c) 2014 Microsoft Corporation
+
+Module Name:
+
+    sls_engine.h
+
+Abstract:
+
+    A Stochastic Local Search (SLS) engine
+
+Author:
+
+    Christoph (cwinter) 2014-03-19
+
+Notes:
+
+--*/
+#ifndef _SLS_ENGINE_H_
+#define _SLS_ENGINE_H_
+
+#include"stopwatch.h"
+#include"lbool.h"
+#include"model_converter.h"
+
+#include"sls_compilation_settings.h"
+#include"sls_tracker.h"
+#include"sls_evaluator.h"
+
+class sls_engine {
+public:
+    class stats {
+    public:
+        unsigned        m_restarts;
+        stopwatch       m_stopwatch;
+        unsigned        m_full_evals;
+        unsigned        m_incr_evals;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+
+        stats() :
+            m_restarts(0),
+            m_full_evals(0),
+            m_incr_evals(0),
+            m_moves(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
+            m_flips(0),
+            m_incs(0),
+            m_decs(0),
+            m_invs(0) {
+            m_stopwatch.reset();
+            m_stopwatch.start();
+        }
+        void reset() {
+            m_full_evals = m_flips = m_incr_evals = 0;
+            m_stopwatch.reset();
+            m_stopwatch.start();
+        }
+    };
+
+protected:
+    ast_manager   & m_manager;
+    stats           m_stats;
+    unsynch_mpz_manager m_mpz_manager;
+    powers          m_powers;
+    mpz             m_zero, m_one, m_two;
+    bool            m_produce_models;
+    volatile bool   m_cancel;
+    bv_util         m_bv_util;
+    sls_tracker     m_tracker;
+    sls_evaluator   m_evaluator;
+
+    unsigned		m_restart_limit;
+    unsigned        m_max_restarts;
+    unsigned        m_plateau_limit;
+
+    ptr_vector<mpz> m_old_values;
+
+    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;
+
+public:    
+    sls_engine(ast_manager & m, params_ref const & p);
+    ~sls_engine();
+
+    ast_manager & m() const { return m_manager; }
+
+    void set_cancel(bool f) { m_cancel = f; }
+    void cancel() { set_cancel(true); }
+    void reset_cancel() { set_cancel(false); }
+
+    void updt_params(params_ref const & _p);
+
+    stats const & get_stats(void) { return m_stats; }
+    void reset_statistics(void) { m_stats.reset(); }    
+
+    bool full_eval(goal_ref const & g, model & mdl);
+    
+
+    void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
+    void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
+    void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result);
+    void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
+    void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
+    void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
+
+    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    
+    
+    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
+    
+    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    
+
+    lbool search(goal_ref const & g);    
+
+    void operator()(goal_ref const & g, model_converter_ref & mc);
+
+protected:
+    void checkpoint();
+    lbool search_old(goal_ref const & g);
+    double get_restart_armin(unsigned cnt_restarts);    
+
+    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                 double & best_score, unsigned & best_const, mpz & best_value);
+
+    bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                       double & best_score, unsigned & best_const, mpz & best_value);
+
+    double top_score(goal_ref const & g);
+    double rescore(goal_ref const & g);
+    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+
+#if _EARLY_PRUNE_
+    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
+#endif
+
+    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+
+    void mk_random_move(ptr_vector<func_decl> & unsat_constants);
+    void mk_random_move(goal_ref const & g);
+
+    bool handle_plateau(goal_ref const & g);
+    bool handle_plateau(goal_ref const & g, double old_score);
+
+    inline unsigned check_restart(unsigned curr_value);
+};
+
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 696d7664a..9daf93c32 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -20,6 +20,9 @@ Notes:
 #ifndef _SLS_EVALUATOR_H_
 #define _SLS_EVALUATOR_H_
 
+#include"model_evaluator.h"
+
+#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 #include"sls_tracker.h"
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index ada0ec359..0f157d3a6 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,1364 +16,31 @@ Author:
 Notes:
 
 --*/
-#include<iomanip>
-#include"map.h"
 #include"nnf.h"
-#include"cooperate.h"
-#include"ast_smt2_pp.h"
-#include"ast_pp.h"
-#include"var_subst.h"
-#include"model_pp.h"
-#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
-#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"stopwatch.h"
 #include"propagate_values_tactic.h"
-#include"sls_tactic.h"
+#include"ctx_simplify_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"nnf_tactic.h"
-#include"luby.h"
-#include "ctx_simplify_tactic.h"
-
-// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
-// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
-#define _BFS_ 0
-
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
-#define _FOCUS_ 1
-
-// probability of choosing the same assertion again in the next step
-#define _PERC_STICKY_ 0
-
-// do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 0
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
-// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 3.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// should score of discunctions be calculated by multiplication of the inverse score rather than min?
-#define _SCORE_OR_MUL_ 0
-
-// do we use some kind of variable neighbourhood-search?
-// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
-#define _VNS_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no
-// 1 = yes, by multiplying it with some factor
-// 2 = yes, by squaring it
-// 3 = yes, by setting it to zero
-// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.25
-
-// shall we toggle the weight after each restart?
-#define _WEIGHT_TOGGLE_ 0
-
-// do we use intensification steps in local minima? if so, how many?
-#define _INTENSIFICATION_ 0
-#define _INTENSIFICATION_TRIES_ 0
-
-// what is the percentage of random moves in plateaus (instead of full randomization)?
-#define _PERC_PLATEAU_MOVES_ 0
-
-// shall we repick clause when randomizing in a plateau or use the current one?
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 10.0
-
-// is uct clause selection probabilistic similar to variable selection in sparrow?
-// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
-#define _PROBABILISTIC_UCT_ 0
-
-// additive constants for probabilistic uct > 0
-#define _UCT_EPS_ 0.0001
-
-// shall we reset _UCT_ touched values after restart?
-#define _UCT_RESET_ 0
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 1
-
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
-// shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 0
-
-// shall we try multiplication by 3?
-#define _USE_MUL3_ 0
-
-// shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 0
-
-// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 0
-
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
-#define _REAL_RS_ 0
-#define _REAL_PBFS_ 0
-
-// how many bits do we neglect in each iteration?
-#define _SKIP_BITS_ 0
-
-// when randomizing local, what is the probability for changing a single bit?
-// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
-#define _PERC_CHANGE_ 0
-
-// do we use random steps for noise?
-// 0 = no, 1 = randomize local, 2 = make random move
-#define _TYPE_RSTEP_ 0
-
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
-
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-
-#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
-    InvalidConfiguration;
-#endif
-#if (_PROBABILISTIC_UCT_ && !_UCT_)
-    InvalidConfiguration;
-#endif
-#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
-    InvalidConfiguration;
-#endif
-#if (_PERC_CHANGE_ == 50)
-    InvalidConfiguration;
-#endif
-#if (_PERC_STICKY_ && !_FOCUS_)
-    InvalidConfiguration;
-#endif
+#include"stopwatch.h"
 
+#include"sls_tactic.h"
 #include"sls_params.hpp"
-#include"sls_evaluator.h"
-#include"sls_tracker.h"
+#include"sls_engine.h"
 
-class sls_tactic : public tactic {
-    class stats {
-    public:
-        unsigned        m_restarts;
-        stopwatch       m_stopwatch;    
-        unsigned        m_full_evals;
-        unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
-
-        stats() :
-            m_restarts(0),
-            m_full_evals(0),
-            m_incr_evals(0),
-            m_moves(0),
-            m_umins(0),
-            m_mul2s(0),
-            m_mul3s(0),
-            m_div2s(0),
-            m_flips(0),
-            m_incs(0),
-            m_decs(0),
-            m_invs(0) {
-                m_stopwatch.reset();
-                m_stopwatch.start();
-            }
-        void reset() {
-            m_full_evals = m_flips = m_incr_evals = 0;
-            m_stopwatch.reset();
-            m_stopwatch.start();
-        }
-    };    
-
-    struct imp {       
-        ast_manager   & m_manager;
-        stats         & m_stats;
-        unsynch_mpz_manager m_mpz_manager;
-        powers          m_powers;
-        mpz             m_zero, m_one, m_two;            
-        bool            m_produce_models;
-        volatile bool   m_cancel;    
-        bv_util         m_bv_util;
-        sls_tracker     m_tracker;
-        sls_evaluator   m_evaluator;
-
-        unsigned		m_restart_limit;
-        unsigned        m_max_restarts;
-        unsigned        m_plateau_limit;
-
-        ptr_vector<mpz> m_old_values;
-        
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
-
-        imp(ast_manager & m, params_ref const & p, stats & s) : 
-            m_manager(m),
-            m_stats(s),
-            m_powers(m_mpz_manager),
-            m_zero(m_mpz_manager.mk_z(0)),
-            m_one(m_mpz_manager.mk_z(1)),
-            m_two(m_mpz_manager.mk_z(2)),
-            m_cancel(false),
-            m_bv_util(m),
-            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
-            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
-        {
-            updt_params(p);
-        }
-
-        ~imp() {
-            m_mpz_manager.del(m_zero);
-            m_mpz_manager.del(m_one);
-            m_mpz_manager.del(m_two);
-        }        
-
-        double get_restart_armin(unsigned cnt_restarts)
-        {
-            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-            //printf("armin: %f\n", pow(1.1, inner_id + 1));
-            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
-        }
-
-        inline unsigned check_restart(unsigned curr_value)
-        {
-            if (curr_value > m_restart_limit)
-            {
-#if _RESTART_SCHEME_ == 4
-                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
-#elif _RESTART_SCHEME_ == 3
-                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 2
-                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 1
-                if (m_stats.m_restarts & 1)
-                    m_restart_limit += _RESTART_LIMIT_;
-                else
-                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
-#else
-                    m_restart_limit += _RESTART_LIMIT_;
-#endif
-#if _WEIGHT_TOGGLE_
-                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-#endif
-                return 0;
-            }
-            return 1;
-        }
-
-        ast_manager & m() const { return m_manager; }
-
-        void set_cancel(bool f) { m_cancel = f; }
-        void cancel() { set_cancel(true); }
-        void reset_cancel() { set_cancel(false); }
-
-        static void collect_param_descrs(param_descrs & r) {
-            sls_params::collect_param_descrs(r);
-        }
-
-        void updt_params(params_ref const & _p) {
-            sls_params p(_p);
-            m_produce_models = _p.get_bool("model", false);
-            m_max_restarts = p.restarts();            
-            m_tracker.set_random_seed(p.random_seed());
-            m_plateau_limit = p.plateau_limit();
-        }
-
-        void checkpoint() { 
-            if (m_cancel)
-                throw tactic_exception(TACTIC_CANCELED_MSG);
-            cooperate("sls");
-        }
-
-        bool full_eval(goal_ref const & g, model & mdl) {
-            bool res = true;
-
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz && res; i++) {
-                checkpoint();
-                expr_ref o(m_manager);
-
-                if (!mdl.eval(g->form(i), o, true))
-                    exit(ERR_INTERNAL_FATAL);
-
-                res = m_manager.is_true(o.get());
-            }        
-
-            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
-
-            return res;
-        }
-
-        double top_score(goal_ref const & g) {
-            #if 0
-            double min = m_tracker.get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
-                double q = m_tracker.get_score(g->form(i));
-                if (q < min) min = q;
-            }
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                for (unsigned i = 0; i < sz; i++)
-                                    tout << " " << m_tracker.get_score(g->form(i));
-                                tout << " MIN: " << min << std::endl; );
-            return min;
-            #else
-            double top_sum = 0.0;
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                top_sum += m_tracker.get_score(e);
-            }
-
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                    for (unsigned i = 0; i < sz; i++)
-                                        tout << " " << m_tracker.get_score(g->form(i));
-                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
-
-#if _CACHE_TOP_SCORE_
-            m_tracker.set_top_sum(top_sum);
-#endif
-
-            return top_sum / (double) sz;
-            #endif
-        }
-
-        double rescore(goal_ref const & g) {
-            m_evaluator.update_all();
-            m_stats.m_full_evals++;
-            return top_score(g);
-        }
-
-        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.serious_update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-#if _EARLY_PRUNE_
-        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_stats.m_incr_evals++;
-            if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
-                return (m_tracker.get_top_sum() / g->size());
-#else
-                return top_score(g);
-#endif
-            else
-                return 0.0;
-        }
-#endif
-
-        // checks whether the score outcome of a given move is better than the previous score
-        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-
-            #ifdef Z3DEBUG
-            mpz old_value;
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-            #endif
-
-#if _EARLY_PRUNE_
-            double r = incremental_score_prune(g, fd, temp);
-#else
-            double r = incremental_score(g, fd, temp);
-#endif   
-            #ifdef Z3DEBUG
-            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
-                                        " --> " << r << std::endl; );
-        
-            m_mpz_manager.del(old_value);
-            #endif
-
-//            if (r >= best_score) {
-            if (r > best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // same as what_if, but only applied to the score of a specific atom, not the total score
-        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-            m_evaluator.update(fd, temp);
-            double r = m_tracker.get_score(e);
-            if (r >= best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.add(old_value, add_value, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-
-        }
-
-        // Andreas: do we really need all those temporary mpzs?
-        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.mul(old_value, m_two, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-        }
-
-        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            m_mpz_manager.div(old_value, m_two, result);
-        }
-
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
-            unsigned shift;        
-            m_mpz_manager.add(old_value, m_one, incremented);
-            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
-                m_mpz_manager.set(incremented, m_zero);
-        }
-
-        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
-            if (m_mpz_manager.is_zero(old_value)) {
-                m_mpz_manager.set(decremented, m_powers(bv_sz));
-                m_mpz_manager.dec(decremented);
-            }
-            else
-                m_mpz_manager.sub(old_value, m_one, decremented);
-        }
-
-        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
-            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
-        }
-
-        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
-            m_mpz_manager.set(flipped, m_zero);
-
-            if (m_bv_util.is_bv_sort(s)) {
-                mpz mask;
-                m_mpz_manager.set(mask, m_powers(bit));
-                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
-                m_mpz_manager.del(mask);
-            }
-            else if (m_manager.is_bool(s))
-                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
-            else
-                NOT_IMPLEMENTED_YET();
-        }
-
-        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
-        {
-            unsigned rnd_mv = 0;
-
-            unsigned ucc = unsat_constants.size(); 
-            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
-            func_decl * fd = unsat_constants[rc];
-
-            mpz new_value;
-
-            sort * srt = fd->get_range();
-            if (m_manager.is_bool(srt))
-                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-            else
-            {
-#if _USE_ADDSUB_
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-                move_type mt = (move_type) rnd_mv;
-
-                // inversion doesn't make sense, let's do a flip instead.
-                if (mt == MV_INV) mt = MV_FLIP;
-#else
-                mt = MV_FLIP;
-#endif
-                unsigned bit = 0;
-
-                switch (mt)
-                {
-                    case MV_FLIP: {
-                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
-                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                    break;
-                }
-                case MV_INC: 
-                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_DEC: 
-                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_INV:
-                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                default:
-                    NOT_IMPLEMENTED_YET();
-                }
-
-                TRACE("sls", tout << "Randomization candidates: ";
-                             for (unsigned i = 0; i < unsat_constants.size(); i++)
-                                 tout << unsat_constants[i]->get_name() << ", ";
-                             tout << std::endl;
-                             tout << "Random move: ";
-                             switch (mt) {
-                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                             }
-                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-            }
-
-            m_evaluator.update(fd, new_value);            
-            m_mpz_manager.del(new_value);
-        }
-
-        void mk_random_move(goal_ref const & g) {
-            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
-        }
-
-        // will use VNS to ignore some possible moves and increase the flips per second
-        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz, max_bv_sz = 0;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-                    // try to flip lsb
-                    mk_flip(srt, old_value, 0, temp);                
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = 0;
-                        move = MV_FLIP;
-                    }
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-
-            // we can either check the condition once in the beginning or check it repeatedly after every bit
-#if _VNS_ == 1
-            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
-#else
-            if (new_score <= score)
-            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
-#endif
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // What would happen if we flipped bit #j ?                
-                if (j < bv_sz)
-                {
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-            mpz temp2;
-#endif
-            unsigned bv_sz;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-#if _SKIP_BITS_
-                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
-#else
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-#endif
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-#endif
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-#if _USE_UNARY_MINUS_
-                    mk_inc(bv_sz, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_UMIN;
-#endif
-
-#if _USE_MUL2DIV2_
-                    // try multiplication by 2
-                    mk_mul2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_MUL2;
-
-#if _USE_MUL3_
-                    // try multiplication by 3
-                    mk_add(bv_sz, old_value, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_MUL3;
-#endif
-
-                    // try division by 2
-                    mk_div2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_DIV2;
-#endif
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                // Andreas: does not hold anymore now that we use top level score caching
-                //SASSERT(check == score);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-#if _USE_MUL3_
-            m_mpz_manager.del(temp2);
-#endif
-            return new_score;
-        }        
-
-        // same as find_best_move but only considers the score of the current expression instead of the overall score
-        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz;
-            double new_score = m_tracker.get_score(e);
-            // Andreas: tie breaking not implemented yet
-            // double tie_score = top_score(g);
-            for (unsigned i = 0; i < to_evaluate.size(); i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz; j++) {
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-                }
-
-                // reset to what it was before
-                m_evaluator.update(fd, old_value);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // first try of intensification ... does not seem to be efficient
-        bool handle_plateau(goal_ref const & g)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned pos = m_stats.m_moves % sz;
-#else
-            unsigned pos = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-            {
-                m_tracker.get_value(to_evaluate[i]);
-                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-            }            
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-            {
-                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
-                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    // Andreas: Actually this should never happen.
-                    NOT_IMPLEMENTED_YET();
-                } else {
-                    m_stats.m_moves++;
-                    func_decl * fd = to_evaluate[new_const];
-
-                    switch (move) {
-                    case MV_FLIP: m_stats.m_flips++; break;
-                    case MV_INC: m_stats.m_incs++; break;
-                    case MV_DEC: m_stats.m_decs++; break;
-                    case MV_INV: m_stats.m_invs++; break;
-                    case MV_UMIN: m_stats.m_umins++; break;
-                    case MV_MUL2: m_stats.m_mul2s++; break;
-                    case MV_MUL3: m_stats.m_mul3s++; break;
-                    case MV_DIV2: m_stats.m_div2s++; break;
-                    }
-                    
-                    m_evaluator.update(fd, new_value);
-                }
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
-
-            m_old_values.reset();
-
-            return 0;
-        }
-
-        // what_if version needed in the context of 2nd intensification try, combining local and global score
-        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
-                        double & best_score, mpz & best_value, unsigned i) {
-        
-            double global_score = incremental_score(g, fd, temp);
-            double local_score = m_tracker.get_score(e);
-            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
-
-            if (new_score >= best_score) {
-                best_score = new_score;
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // find_best_move version needed in the context of 2nd intensification try
-        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-        {
-            mpz old_value, temp;
-            double best_score = 0;
-
-            sort * srt = fd->get_range();
-            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
-                mk_flip(srt, old_value, j, temp);                
-                what_if(g, e, fd, temp, best_score, best_value, i); 
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-
-            return best_score;
-        }        
-
-        // second try to use intensification ... also not very effective
-        bool handle_plateau(goal_ref const & g, double old_score)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned new_const = m_stats.m_moves % sz;
-#else
-            unsigned new_const = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-
-            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-            func_decl * fd = to_evaluate[new_const];
-
-            mpz new_value;
-            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-            unsigned new_bit = 0;        
-            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-            
-            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-            {
-                new_score = find_best_move_local(g, q, fd, new_value, i);
-
-                m_stats.m_moves++;
-                m_stats.m_flips++;
-
-                global_score = incremental_score(g, fd, new_value);
-                local_score = m_tracker.get_score(q);
-
-                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            return 0;
-        }
-
-        // main search loop
-        lbool search(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            unsigned plateau_cnt = 0;
-
-            score = rescore(g);
-            unsigned sz = g->size();
-#if _PERC_STICKY_
-            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-
-#if _RESTARTS_ == 1
-            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 2
-            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 3
-            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#endif
-                checkpoint();
-                m_stats.m_moves++;
-
-#if _REAL_RS_ || _REAL_PBFS_
-                //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
-
-#if _FOCUS_
-#if _PERC_STICKY_
-                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
-                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#else
-                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-                if (!e)
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
-                if (!to_evaluate.size())
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-#endif
-
-#if _TYPE_RSTEP_
-                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                {
-#if _TYPE_RSTEP_ == 1
-                    m_evaluator.randomize_local(to_evaluate);
-#elif _TYPE_RSTEP_ == 2
-                    mk_random_move(to_evaluate);
-#endif
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                }
-                continue;
-#endif
-
-#if _WEIGHT_DIST_ == 4
-                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif       
-                old_score = score;
-                new_const = (unsigned)-1;
-
-#if _VNS_
-                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    score = old_score;
-                    plateau_cnt++;
-#if _INTENSIFICATION_
-                    handle_plateau(g, score);
-                    //handle_plateau(g);
-                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-#if _PERC_PLATEAU_MOVES_
-                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
-                        mk_random_move(to_evaluate);
-                    else
-#endif
-#if _REPICK_
-                    m_evaluator.randomize_local(g, m_stats.m_moves);
-#else
-                    m_evaluator.randomize_local(to_evaluate);
-#endif
-#endif
-
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                } else {
-                    func_decl * fd = to_evaluate[new_const];              
-#if _REAL_RS_ || _REAL_PBFS_
-                    score = serious_score(g, fd, new_value);
-#else
-                    score = incremental_score(g, fd, new_value);    
-#endif
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        // main search loop
-        lbool search_old(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            
-            score = rescore(g);
-            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-                         tout << "Score distribution:"; 
-                         for (unsigned i = 0; i < g->size(); i++)
-                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                         tout << " TOP: " << score << std::endl; ); 
-        
-            unsigned plateau_cnt = 0;
-
-            // Andreas: Why do we only allow so few plateaus?
-#if _RESTARTS_
-            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
-            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
-#endif
-                do {
-                    checkpoint();
-
-#if _WEIGHT_DIST_ == 4
-                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-            
-#if _TYPE_RSTEP_
-                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                    {
-#if _TYPE_RSTEP_ == 1
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _TYPE_RSTEP_ == 2
-                        mk_random_move(g);
-#endif
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                            } else
-                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                        }
-                    }
-#endif
-                    old_score = score;
-                    new_const = (unsigned)-1;
-                        
-                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-                    if (!to_evaluate.size())
-                    {
-                        res = l_true;
-                        goto bailout;
-                    }
-                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
-                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
-                                                tout << to_evaluate[i]->get_name() << std::endl; );
-
-#if _VNS_
-                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-                    if (new_const == static_cast<unsigned>(-1)) {
-                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
-                                        for (unsigned i = 0; i < g->size(); i++) {
-                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
-                                        });
-
-                        TRACE("sls_max", m_tracker.show_model(tout);
-                                        tout << "Scores: " << std::endl;
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
-                                            m_tracker.get_score(g->form(i)) << std::endl; );
-                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
-                        score = old_score;
-                    }
-                    else {
-                        // Andreas: Why does randomizing not count as a move? (Now it does.)
-                        m_stats.m_moves++;
-                        func_decl * fd = to_evaluate[new_const];
-
-                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
-                                        switch (move) {
-                                        case MV_FLIP:  
-                                            tout << "Flip";
-                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
-                                            break;
-                                        case MV_INC: 
-                                            tout << "+1";
-                                            break;
-                                        case MV_DEC: 
-                                            tout << "-1";
-                                            break;
-                                        case MV_INV: 
-                                            tout << "NEG";
-                                            break;
-                                        };                                        
-                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
-
-                        switch (move) {
-                        case MV_FLIP: m_stats.m_flips++; break;
-                        case MV_INC: m_stats.m_incs++; break;
-                        case MV_DEC: m_stats.m_decs++; break;
-                        case MV_INV: m_stats.m_invs++; break;
-                        case MV_UMIN: m_stats.m_umins++; break;
-                        case MV_MUL2: m_stats.m_mul2s++; break;
-                        case MV_MUL3: m_stats.m_mul3s++; break;
-                        case MV_DIV2: m_stats.m_div2s++; break;
-                        }
-                    
-#if _REAL_RS_ || _REAL_PBFS_
-                        score = serious_score(g, fd, new_value);
-#else
-                        score = incremental_score(g, fd, new_value);    
-#endif
-
-                        TRACE("sls", tout << "Score distribution:"; 
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                                        tout << " TOP: " << score << std::endl; );                        
-                    }
-
-                    if (score >= 0.99999) {
-//                    if (score >= 1.0) {
-                        // score could theoretically be imprecise.
-                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
-                        bool all_true = true;
-                        for (unsigned i = 0; i < g->size() && all_true; i++)
-                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                all_true=false;
-                        if (all_true) {
-                            res = l_true; // sat
-                            goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                    /*
-                    if (m_stats.m_moves % 100 == 0)
-                    {
-                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-                    }*/
-                }
-                while (score > old_score && res == l_undef);                
-                
-                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
-                if (score != old_score) {
-                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
-                    plateau_cnt = 0;
-                } else {
-                    m_stats.m_moves++;
-                    plateau_cnt++;
-                    //report_tactic_progress("Plateau.", plateau_cnt);
-                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
-                    //if (plateau_cnt < m_plateau_limit) {
-                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
-#if _INTENSIFICATION_
-                        handle_plateau(g, score);
-                        //handle_plateau(g);
-#else
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#endif
-                        //mk_random_move(g);
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        void operator()(goal_ref const & g, model_converter_ref & mc) {
-            if (g->inconsistent()) {
-                mc = 0;
-                return;
-            }
-
-            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
-            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
-            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
-            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
-            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-            
-#if _WEIGHT_DIST_ == 4
-            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-            m_tracker.initialize(g);
-            lbool res = l_undef;
-        
-            m_restart_limit = _RESTART_LIMIT_;
-
-            do {
-                checkpoint();
-
-                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                res = search(g);
-
-                if (res == l_undef)
-                {
-#if _RESTART_INIT_
-                    m_tracker.randomize(g);
-#else
-                    m_tracker.reset(g);
-#endif
-                }
-            }
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-        
-            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-            if (res == l_true) {    
-                report_tactic_progress("Number of flips:", m_stats.m_moves);
-                for (unsigned i = 0; i < g->size(); i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                    {
-                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                        NOT_IMPLEMENTED_YET(); 
-                    }
-
-                if (m_produce_models) {
-                    model_ref mdl = m_tracker.get_model();
-                    mc = model2model_converter(mdl.get());
-                    TRACE("sls_model", mc->display(tout); );
-                }
-                g->reset();
-            }
-            else
-                mc = 0;
-        }
-    };
-    
+class sls_tactic : public tactic {    
     ast_manager    & m;
     params_ref       m_params;
-    imp            * m_imp;
-    stats            m_stats;
+    sls_engine     * m_engine;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_imp = alloc(imp, m, p, m_stats);
+        m_engine = alloc(sls_engine, m, p);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -1381,16 +48,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_imp);
+        dealloc(m_engine);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_imp->updt_params(p);
+        m_engine->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        imp::collect_param_descrs(r);
+        sls_params::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -1398,14 +65,13 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());
-        m_imp->m_produce_models = g->models_enabled();        
+        SASSERT(g->is_well_sorted());        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_imp->operator()(g, mc);
+        m_engine->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -1414,40 +80,41 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = m_imp;
+        sls_engine * d = m_engine;
         #pragma omp critical (tactic_cancel)
         {
-            d = m_imp;
+            d = m_engine;
         }
         dealloc(d);
-        d = alloc(imp, m, m_params, m_stats);
+        d = alloc(sls_engine, m, m_params);
         #pragma omp critical (tactic_cancel) 
         {
-            m_imp = d;
+            m_engine = d;
         }
     }
     
     virtual void collect_statistics(statistics & st) const {
-        double seconds = m_stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", m_stats.m_restarts);
-        st.update("sls full evals", m_stats.m_full_evals);
-        st.update("sls incr evals", m_stats.m_incr_evals);
-        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
-        st.update("sls FLIP moves", m_stats.m_flips);    
-        st.update("sls INC moves", m_stats.m_incs);
-        st.update("sls DEC moves", m_stats.m_decs);
-        st.update("sls INV moves", m_stats.m_invs);
-        st.update("sls moves", m_stats.m_moves);
-        st.update("sls moves/sec", m_stats.m_moves / seconds);
+        sls_engine::stats const & stats = m_engine->get_stats();
+        double seconds = stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", stats.m_restarts);
+        st.update("sls full evals", stats.m_full_evals);
+        st.update("sls incr evals", stats.m_incr_evals);
+        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
+        st.update("sls FLIP moves", stats.m_flips);
+        st.update("sls INC moves", stats.m_incs);
+        st.update("sls DEC moves", stats.m_decs);
+        st.update("sls INV moves", stats.m_invs);
+        st.update("sls moves", stats.m_moves);
+        st.update("sls moves/sec", stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_stats.reset();
+        m_engine->reset_statistics();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_imp)
-            m_imp->set_cancel(f);
+        if (m_engine)
+            m_engine->set_cancel(f);
     }
 };
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 0aca1f59c..3675265ee 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,6 +20,12 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
+#include"goal.h"
+#include"model.h"
+
+#include"sls_compilation_settings.h"
+#include"sls_powers.h"
+
 class sls_tracker {
     ast_manager         & m_manager;
     unsynch_mpz_manager & m_mpz_manager;
@@ -1186,7 +1192,7 @@ public:
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); 
 #elif _UCT_ == 2
                 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif
@@ -1334,7 +1340,7 @@ public:
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif

From a6227d5446d206a2d264f2305a08953288a4eae7 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 17:26:05 +0000
Subject: [PATCH 040/108] SLS refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index aea4787b0..8e52596e0 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -18,6 +18,10 @@ Notes:
     This file should go away completely once we have evaluated all options.
 
 --*/
+
+#ifndef _SLS_COMPILATION_SETTINGS_H_
+#define _SLS_COMPILATION_SETTINGS_H_
+
 // which unsatisfied assertion is selected? only works with _FOCUS_ > 0
 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
 #define _BFS_ 0
@@ -155,4 +159,6 @@ InvalidConfiguration;
 #endif
 #if (_PERC_STICKY_ && !_FOCUS_)
 InvalidConfiguration;
+#endif
+
 #endif
\ No newline at end of file

From 1e55b3bfb5035e1fa8b44014cab58a036a727216 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Thu, 20 Mar 2014 15:58:53 +0000
Subject: [PATCH 041/108] uct forget and minisat restarts added

---
 src/tactic/sls/sls_tactic.cpp | 1417 ++++++++++++++++++++++++++++++++-
 src/tactic/sls/sls_tracker.h  |   22 +-
 2 files changed, 1402 insertions(+), 37 deletions(-)

diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 0f157d3a6..b2b7035e0 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,31 +16,1378 @@ Author:
 Notes:
 
 --*/
+#include<iomanip>
+#include"map.h"
 #include"nnf.h"
+#include"cooperate.h"
+#include"ast_smt2_pp.h"
+#include"ast_pp.h"
+#include"var_subst.h"
+#include"model_pp.h"
+#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"propagate_values_tactic.h"
-#include"ctx_simplify_tactic.h"
-#include"elim_uncnstr_tactic.h"
-#include"nnf_tactic.h"
 #include"stopwatch.h"
-
+#include"propagate_values_tactic.h"
 #include"sls_tactic.h"
-#include"sls_params.hpp"
-#include"sls_engine.h"
+#include"nnf_tactic.h"
+#include"luby.h"
+#include "ctx_simplify_tactic.h"
 
-class sls_tactic : public tactic {    
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
+#define _FOCUS_ 1
+
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 1
+
+// do we use restarts?
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 4.0
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
+#define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
+#define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
+#define _VNS_ 0
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 1
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.5
+
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 1
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 20.0
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
+#define _PROBABILISTIC_UCT_ 0
+
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// do we gradually reduce the touched values of _UCT_?
+#define _UCT_FORGET_ 0
+#define _UCT_FORGET_FACTOR_ 0.5
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 0
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 0
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 0
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 0
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 0
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
+    InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+    InvalidConfiguration;
+#endif
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+    InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+    InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+    InvalidConfiguration;
+#endif
+
+#include"sls_params.hpp"
+#include"sls_evaluator.h"
+#include"sls_tracker.h"
+
+class sls_tactic : public tactic {
+    class stats {
+    public:
+        unsigned        m_restarts;
+        stopwatch       m_stopwatch;    
+        unsigned        m_full_evals;
+        unsigned        m_incr_evals;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+
+        stats() :
+            m_restarts(0),
+            m_full_evals(0),
+            m_incr_evals(0),
+            m_moves(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
+            m_flips(0),
+            m_incs(0),
+            m_decs(0),
+            m_invs(0) {
+                m_stopwatch.reset();
+                m_stopwatch.start();
+            }
+        void reset() {
+            m_full_evals = m_flips = m_incr_evals = 0;
+            m_stopwatch.reset();
+            m_stopwatch.start();
+        }
+    };    
+
+    struct imp {       
+        ast_manager   & m_manager;
+        stats         & m_stats;
+        unsynch_mpz_manager m_mpz_manager;
+        powers          m_powers;
+        mpz             m_zero, m_one, m_two;            
+        bool            m_produce_models;
+        volatile bool   m_cancel;    
+        bv_util         m_bv_util;
+        sls_tracker     m_tracker;
+        sls_evaluator   m_evaluator;
+
+        unsigned		m_restart_limit;
+        unsigned        m_max_restarts;
+        unsigned        m_plateau_limit;
+
+        ptr_vector<mpz> m_old_values;
+        
+        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
+
+        imp(ast_manager & m, params_ref const & p, stats & s) : 
+            m_manager(m),
+            m_stats(s),
+            m_powers(m_mpz_manager),
+            m_zero(m_mpz_manager.mk_z(0)),
+            m_one(m_mpz_manager.mk_z(1)),
+            m_two(m_mpz_manager.mk_z(2)),
+            m_cancel(false),
+            m_bv_util(m),
+            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
+            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
+        {
+            updt_params(p);
+        }
+
+        ~imp() {
+            m_mpz_manager.del(m_zero);
+            m_mpz_manager.del(m_one);
+            m_mpz_manager.del(m_two);
+        }        
+
+        double get_restart_armin(unsigned cnt_restarts)
+        {
+            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+            //printf("armin: %f\n", pow(1.1, inner_id + 1));
+            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
+        }
+
+        inline unsigned check_restart(unsigned curr_value)
+        {
+            if (curr_value > m_restart_limit)
+            {
+#if _RESTART_SCHEME_ == 5
+                m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+#elif _RESTART_SCHEME_ == 4
+                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+#elif _RESTART_SCHEME_ == 3
+                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 2
+                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 1
+                if (m_stats.m_restarts & 1)
+                    m_restart_limit += _RESTART_LIMIT_;
+                else
+                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+#else
+                    m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
+                return 0;
+            }
+            return 1;
+        }
+
+        ast_manager & m() const { return m_manager; }
+
+        void set_cancel(bool f) { m_cancel = f; }
+        void cancel() { set_cancel(true); }
+        void reset_cancel() { set_cancel(false); }
+
+        static void collect_param_descrs(param_descrs & r) {
+            sls_params::collect_param_descrs(r);
+        }
+
+        void updt_params(params_ref const & _p) {
+            sls_params p(_p);
+            m_produce_models = _p.get_bool("model", false);
+            m_max_restarts = p.restarts();            
+            m_tracker.set_random_seed(p.random_seed());
+            m_plateau_limit = p.plateau_limit();
+        }
+
+        void checkpoint() { 
+            if (m_cancel)
+                throw tactic_exception(TACTIC_CANCELED_MSG);
+            cooperate("sls");
+        }
+
+        bool full_eval(goal_ref const & g, model & mdl) {
+            bool res = true;
+
+            unsigned sz = g->size();
+            for (unsigned i = 0; i < sz && res; i++) {
+                checkpoint();
+                expr_ref o(m_manager);
+
+                if (!mdl.eval(g->form(i), o, true))
+                    exit(ERR_INTERNAL_FATAL);
+
+                res = m_manager.is_true(o.get());
+            }        
+
+            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
+
+            return res;
+        }
+
+        double top_score(goal_ref const & g) {
+            #if 0
+            double min = m_tracker.get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+                double q = m_tracker.get_score(g->form(i));
+                if (q < min) min = q;
+            }
+            TRACE("sls_top", tout << "Score distribution:"; 
+                                for (unsigned i = 0; i < sz; i++)
+                                    tout << " " << m_tracker.get_score(g->form(i));
+                                tout << " MIN: " << min << std::endl; );
+            return min;
+            #else
+            double top_sum = 0.0;
+            unsigned sz = g->size();
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+                top_sum += m_tracker.get_score(e);
+            }
+
+            TRACE("sls_top", tout << "Score distribution:"; 
+                                    for (unsigned i = 0; i < sz; i++)
+                                        tout << " " << m_tracker.get_score(g->form(i));
+                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
+
+#if _CACHE_TOP_SCORE_
+            m_tracker.set_top_sum(top_sum);
+#endif
+
+            return top_sum / (double) sz;
+            #endif
+        }
+
+        double rescore(goal_ref const & g) {
+            m_evaluator.update_all();
+            m_stats.m_full_evals++;
+            return top_score(g);
+        }
+
+        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_evaluator.serious_update(fd, new_value);
+            m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+            return (m_tracker.get_top_sum() / g->size());
+#else
+            return top_score(g);
+#endif
+        }
+
+        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_evaluator.update(fd, new_value);
+            m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+            return (m_tracker.get_top_sum() / g->size());
+#else
+            return top_score(g);
+#endif
+        }
+
+#if _EARLY_PRUNE_
+        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_stats.m_incr_evals++;
+            if (m_evaluator.update_prune(fd, new_value))
+#if _CACHE_TOP_SCORE_
+                return (m_tracker.get_top_sum() / g->size());
+#else
+                return top_score(g);
+#endif
+            else
+                return 0.0;
+        }
+#endif
+
+        // checks whether the score outcome of a given move is better than the previous score
+        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+
+            #ifdef Z3DEBUG
+            mpz old_value;
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+            #endif
+
+#if _EARLY_PRUNE_
+            double r = incremental_score_prune(g, fd, temp);
+#else
+            double r = incremental_score(g, fd, temp);
+#endif   
+            #ifdef Z3DEBUG
+            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
+                                        " --> " << r << std::endl; );
+        
+            m_mpz_manager.del(old_value);
+            #endif
+
+//            if (r >= best_score) {
+            if (r > best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+        // same as what_if, but only applied to the score of a specific atom, not the total score
+        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+            m_evaluator.update(fd, temp);
+            double r = m_tracker.get_score(e);
+            if (r >= best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.add(old_value, add_value, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
+
+        }
+
+        // Andreas: do we really need all those temporary mpzs?
+        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.mul(old_value, m_two, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
+        }
+
+        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            m_mpz_manager.div(old_value, m_two, result);
+        }
+
+        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+            unsigned shift;        
+            m_mpz_manager.add(old_value, m_one, incremented);
+            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
+                m_mpz_manager.set(incremented, m_zero);
+        }
+
+        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
+            if (m_mpz_manager.is_zero(old_value)) {
+                m_mpz_manager.set(decremented, m_powers(bv_sz));
+                m_mpz_manager.dec(decremented);
+            }
+            else
+                m_mpz_manager.sub(old_value, m_one, decremented);
+        }
+
+        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
+            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
+        }
+
+        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
+            m_mpz_manager.set(flipped, m_zero);
+
+            if (m_bv_util.is_bv_sort(s)) {
+                mpz mask;
+                m_mpz_manager.set(mask, m_powers(bit));
+                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
+                m_mpz_manager.del(mask);
+            }
+            else if (m_manager.is_bool(s))
+                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
+            else
+                NOT_IMPLEMENTED_YET();
+        }
+
+        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
+        {
+            unsigned rnd_mv = 0;
+            unsigned ucc = unsat_constants.size(); 
+            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
+            func_decl * fd = unsat_constants[rc];
+
+            mpz new_value;
+
+            sort * srt = fd->get_range();
+            if (m_manager.is_bool(srt))
+                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+            else
+            {
+#if _USE_ADDSUB_
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+                move_type mt = (move_type) rnd_mv;
+
+                // inversion doesn't make sense, let's do a flip instead.
+                if (mt == MV_INV) mt = MV_FLIP;
+#else
+                mt = MV_FLIP;
+#endif
+                unsigned bit = 0;
+
+                switch (mt)
+                {
+                    case MV_FLIP: {
+                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
+                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+                    break;
+                }
+                case MV_INC: 
+                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_DEC: 
+                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_INV:
+                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                default:
+                    NOT_IMPLEMENTED_YET();
+                }
+
+                TRACE("sls", tout << "Randomization candidates: ";
+                             for (unsigned i = 0; i < unsat_constants.size(); i++)
+                                 tout << unsat_constants[i]->get_name() << ", ";
+                             tout << std::endl;
+                             tout << "Random move: ";
+                             switch (mt) {
+                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+                             }
+                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+            }
+
+            m_evaluator.update(fd, new_value);            
+            m_mpz_manager.del(new_value);
+        }
+
+        void mk_random_move(goal_ref const & g) {
+            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
+        }
+
+        // will use VNS to ignore some possible moves and increase the flips per second
+        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz, max_bv_sz = 0;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+
+                    // try to flip lsb
+                    mk_flip(srt, old_value, 0, temp);                
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = 0;
+                        move = MV_FLIP;
+                    }
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+
+            // we can either check the condition once in the beginning or check it repeatedly after every bit
+#if _VNS_ == 1
+            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+            if (new_score <= score)
+            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
+        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+            mpz temp2;
+#endif
+            unsigned bv_sz;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+#if _SKIP_BITS_
+                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+#else
+                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+#if _USE_ADDSUB_
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+#endif
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+                    mk_inc(bv_sz, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+                    // try multiplication by 2
+                    mk_mul2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_MUL2;
+
+#if _USE_MUL3_
+                    // try multiplication by 3
+                    mk_add(bv_sz, old_value, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_MUL3;
+#endif
+
+                    // try division by 2
+                    mk_div2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_DIV2;
+#endif
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                // Andreas: does not hold anymore now that we use top level score caching
+                //SASSERT(check == score);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+#if _USE_MUL3_
+            m_mpz_manager.del(temp2);
+#endif
+            return new_score;
+        }        
+
+        // same as find_best_move but only considers the score of the current expression instead of the overall score
+        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz;
+            double new_score = m_tracker.get_score(e);
+            // Andreas: tie breaking not implemented yet
+            // double tie_score = top_score(g);
+            for (unsigned i = 0; i < to_evaluate.size(); i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+                for (unsigned j = 0; j < bv_sz; j++) {
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+                }
+
+                // reset to what it was before
+                m_evaluator.update(fd, old_value);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
+        // first try of intensification ... does not seem to be efficient
+        bool handle_plateau(goal_ref const & g)
+        {
+            unsigned sz = g->size();
+#if _BFS_
+            unsigned pos = m_stats.m_moves % sz;
+#else
+            unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+            if (!e)
+                return 0;
+
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+            {
+                m_tracker.get_value(to_evaluate[i]);
+                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+            }            
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+            {
+                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
+                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
+
+                if (new_const == static_cast<unsigned>(-1)) {
+                    // Andreas: Actually this should never happen.
+                    NOT_IMPLEMENTED_YET();
+                } else {
+                    m_stats.m_moves++;
+                    func_decl * fd = to_evaluate[new_const];
+
+                    switch (move) {
+                    case MV_FLIP: m_stats.m_flips++; break;
+                    case MV_INC: m_stats.m_incs++; break;
+                    case MV_DEC: m_stats.m_decs++; break;
+                    case MV_INV: m_stats.m_invs++; break;
+                    case MV_UMIN: m_stats.m_umins++; break;
+                    case MV_MUL2: m_stats.m_mul2s++; break;
+                    case MV_MUL3: m_stats.m_mul3s++; break;
+                    case MV_DIV2: m_stats.m_div2s++; break;
+                    }
+                    
+                    m_evaluator.update(fd, new_value);
+                }
+
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
+
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+
+            m_old_values.reset();
+
+            return 0;
+        }
+
+        // what_if version needed in the context of 2nd intensification try, combining local and global score
+        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
+                        double & best_score, mpz & best_value, unsigned i) {
+        
+            double global_score = incremental_score(g, fd, temp);
+            double local_score = m_tracker.get_score(e);
+            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+            if (new_score >= best_score) {
+                best_score = new_score;
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+        // find_best_move version needed in the context of 2nd intensification try
+        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+        {
+            mpz old_value, temp;
+            double best_score = 0;
+
+            sort * srt = fd->get_range();
+            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+                mk_flip(srt, old_value, j, temp);                
+                what_if(g, e, fd, temp, best_score, best_value, i); 
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+
+            return best_score;
+        }        
+
+        // second try to use intensification ... also not very effective
+        bool handle_plateau(goal_ref const & g, double old_score)
+        {
+            unsigned sz = g->size();
+#if _BFS_
+            unsigned new_const = m_stats.m_moves % sz;
+#else
+            unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+            if (!e)
+                return 0;
+
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+            func_decl * fd = to_evaluate[new_const];
+
+            mpz new_value;
+            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+            unsigned new_bit = 0;        
+            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+            
+            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+            {
+                new_score = find_best_move_local(g, q, fd, new_value, i);
+
+                m_stats.m_moves++;
+                m_stats.m_flips++;
+
+                global_score = incremental_score(g, fd, new_value);
+                local_score = m_tracker.get_score(q);
+
+                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
+
+            return 0;
+        }
+
+        // main search loop
+        lbool search(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            unsigned plateau_cnt = 0;
+
+            score = rescore(g);
+            unsigned sz = g->size();
+#if _PERC_STICKY_
+            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+
+#if _RESTARTS_ == 1
+            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 2
+            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 3
+            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
+                checkpoint();
+                m_stats.m_moves++;
+
+#if _UCT_FORGET_
+                if (m_stats.m_moves % _UCT_FORGET_ == 0)
+                    m_tracker.uct_forget(g);
+#endif
+
+#if _REAL_RS_ || _REAL_PBFS_
+                //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
+
+#if _FOCUS_
+#if _PERC_STICKY_
+                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#else
+                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+                if (!e)
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+                if (!to_evaluate.size())
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+#endif
+
+#if _TYPE_RSTEP_
+                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                {
+#if _TYPE_RSTEP_ == 1
+                    m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
+                    mk_random_move(to_evaluate);
+#endif
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                }
+                continue;
+#endif
+
+#if _WEIGHT_DIST_ == 4
+                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
+                old_score = score;
+                new_const = (unsigned)-1;
+
+#if _VNS_
+                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+
+                if (new_const == static_cast<unsigned>(-1)) {
+                    score = old_score;
+                    plateau_cnt++;
+#if _INTENSIFICATION_
+                    handle_plateau(g, score);
+                    //handle_plateau(g);
+                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                        mk_random_move(to_evaluate);
+                    else
+#endif
+#if _REPICK_
+                    m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
+                    m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
+
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                } else {
+                    func_decl * fd = to_evaluate[new_const];              
+#if _REAL_RS_ || _REAL_PBFS_
+                    score = serious_score(g, fd, new_value);
+#else
+                    score = incremental_score(g, fd, new_value);    
+#endif
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        // main search loop
+        lbool search_old(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            
+            score = rescore(g);
+            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+                         tout << "Score distribution:"; 
+                         for (unsigned i = 0; i < g->size(); i++)
+                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                         tout << " TOP: " << score << std::endl; ); 
+        
+            unsigned plateau_cnt = 0;
+
+            // Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
+#endif
+                do {
+                    checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+            
+#if _TYPE_RSTEP_
+                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                    {
+#if _TYPE_RSTEP_ == 1
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+                        mk_random_move(g);
+#endif
+                        score = top_score(g);
+
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                            } else
+                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                        }
+                    }
+#endif
+                    old_score = score;
+                    new_const = (unsigned)-1;
+                        
+                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+                    if (!to_evaluate.size())
+                    {
+                        res = l_true;
+                        goto bailout;
+                    }
+                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
+                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
+                                                tout << to_evaluate[i]->get_name() << std::endl; );
+
+#if _VNS_
+                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+                    if (new_const == static_cast<unsigned>(-1)) {
+                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
+                                        for (unsigned i = 0; i < g->size(); i++) {
+                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                                        });
+
+                        TRACE("sls_max", m_tracker.show_model(tout);
+                                        tout << "Scores: " << std::endl;
+                                        for (unsigned i = 0; i < g->size(); i++)
+                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
+                                            m_tracker.get_score(g->form(i)) << std::endl; );
+                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                        score = old_score;
+                    }
+                    else {
+                        // Andreas: Why does randomizing not count as a move? (Now it does.)
+                        m_stats.m_moves++;
+                        func_decl * fd = to_evaluate[new_const];
+
+                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
+                                        switch (move) {
+                                        case MV_FLIP:  
+                                            tout << "Flip";
+                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
+                                            break;
+                                        case MV_INC: 
+                                            tout << "+1";
+                                            break;
+                                        case MV_DEC: 
+                                            tout << "-1";
+                                            break;
+                                        case MV_INV: 
+                                            tout << "NEG";
+                                            break;
+                                        };                                        
+                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
+
+                        switch (move) {
+                        case MV_FLIP: m_stats.m_flips++; break;
+                        case MV_INC: m_stats.m_incs++; break;
+                        case MV_DEC: m_stats.m_decs++; break;
+                        case MV_INV: m_stats.m_invs++; break;
+                        case MV_UMIN: m_stats.m_umins++; break;
+                        case MV_MUL2: m_stats.m_mul2s++; break;
+                        case MV_MUL3: m_stats.m_mul3s++; break;
+                        case MV_DIV2: m_stats.m_div2s++; break;
+                        }
+                    
+#if _REAL_RS_ || _REAL_PBFS_
+                        score = serious_score(g, fd, new_value);
+#else
+                        score = incremental_score(g, fd, new_value);    
+#endif
+
+                        TRACE("sls", tout << "Score distribution:"; 
+                                        for (unsigned i = 0; i < g->size(); i++)
+                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                                        tout << " TOP: " << score << std::endl; );                        
+                    }
+
+                    if (score >= 0.99999) {
+//                    if (score >= 1.0) {
+                        // score could theoretically be imprecise.
+                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                        bool all_true = true;
+                        for (unsigned i = 0; i < g->size() && all_true; i++)
+                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                all_true=false;
+                        if (all_true) {
+                            res = l_true; // sat
+                            goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
+                    /*
+                    if (m_stats.m_moves % 100 == 0)
+                    {
+                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+                    }*/
+                }
+                while (score > old_score && res == l_undef);                
+                
+                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                if (score != old_score) {
+                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
+                    plateau_cnt = 0;
+                } else {
+                    m_stats.m_moves++;
+                    plateau_cnt++;
+                    //report_tactic_progress("Plateau.", plateau_cnt);
+                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //if (plateau_cnt < m_plateau_limit) {
+                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
+#if _INTENSIFICATION_
+                        handle_plateau(g, score);
+                        //handle_plateau(g);
+#else
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
+#endif
+                        //mk_random_move(g);
+                        score = top_score(g);
+
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        void operator()(goal_ref const & g, model_converter_ref & mc) {
+            if (g->inconsistent()) {
+                mc = 0;
+                return;
+            }
+
+            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl;
+            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
+            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
+            verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl;
+            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
+            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+            verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
+            verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
+            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+            
+#if _WEIGHT_DIST_ == 4
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+            m_tracker.initialize(g);
+            lbool res = l_undef;
+        
+            m_restart_limit = _RESTART_LIMIT_;
+
+            do {
+                checkpoint();
+
+                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+                res = search(g);
+
+                if (res == l_undef)
+                {
+#if _RESTART_INIT_
+                    m_tracker.randomize(g);
+#else
+                    m_tracker.reset(g);
+#endif
+                }
+            }
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+        
+            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+
+            if (res == l_true) {    
+                report_tactic_progress("Number of flips:", m_stats.m_moves);
+                for (unsigned i = 0; i < g->size(); i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                    {
+                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                        NOT_IMPLEMENTED_YET(); 
+                    }
+
+                if (m_produce_models) {
+                    model_ref mdl = m_tracker.get_model();
+                    mc = model2model_converter(mdl.get());
+                    TRACE("sls_model", mc->display(tout); );
+                }
+                g->reset();
+            }
+            else
+                mc = 0;
+        }
+    };
+    
     ast_manager    & m;
     params_ref       m_params;
-    sls_engine     * m_engine;
+    imp            * m_imp;
+    stats            m_stats;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_engine = alloc(sls_engine, m, p);
+        m_imp = alloc(imp, m, p, m_stats);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -48,16 +1395,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_engine);
+        dealloc(m_imp);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_engine->updt_params(p);
+        m_imp->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        sls_params::collect_param_descrs(r);
+        imp::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -65,13 +1412,14 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());        
+        SASSERT(g->is_well_sorted());
+        m_imp->m_produce_models = g->models_enabled();        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_engine->operator()(g, mc);
+        m_imp->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -80,41 +1428,40 @@ public:
     }
 
     virtual void cleanup() {        
-        sls_engine * d = m_engine;
+        imp * d = m_imp;
         #pragma omp critical (tactic_cancel)
         {
-            d = m_engine;
+            d = m_imp;
         }
         dealloc(d);
-        d = alloc(sls_engine, m, m_params);
+        d = alloc(imp, m, m_params, m_stats);
         #pragma omp critical (tactic_cancel) 
         {
-            m_engine = d;
+            m_imp = d;
         }
     }
     
     virtual void collect_statistics(statistics & st) const {
-        sls_engine::stats const & stats = m_engine->get_stats();
-        double seconds = stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", stats.m_restarts);
-        st.update("sls full evals", stats.m_full_evals);
-        st.update("sls incr evals", stats.m_incr_evals);
-        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
-        st.update("sls FLIP moves", stats.m_flips);
-        st.update("sls INC moves", stats.m_incs);
-        st.update("sls DEC moves", stats.m_decs);
-        st.update("sls INV moves", stats.m_invs);
-        st.update("sls moves", stats.m_moves);
-        st.update("sls moves/sec", stats.m_moves / seconds);
+        double seconds = m_stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", m_stats.m_restarts);
+        st.update("sls full evals", m_stats.m_full_evals);
+        st.update("sls incr evals", m_stats.m_incr_evals);
+        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
+        st.update("sls FLIP moves", m_stats.m_flips);    
+        st.update("sls INC moves", m_stats.m_incs);
+        st.update("sls DEC moves", m_stats.m_decs);
+        st.update("sls INV moves", m_stats.m_invs);
+        st.update("sls moves", m_stats.m_moves);
+        st.update("sls moves/sec", m_stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_engine->reset_statistics();
+        m_stats.reset();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_engine)
-            m_engine->set_cancel(f);
+        if (m_imp)
+            m_imp->set_cancel(f);
     }
 };
 
@@ -163,7 +1510,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                         // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
                         //mk_ctx_simplify_tactic(m, ctx_p),
                         // Andreas: This one at least eliminates top level duplicates ...
-                        mk_simplify_tactic(m),
+                        //mk_simplify_tactic(m),
                         // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 3675265ee..1c33d42a7 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -276,6 +276,20 @@ public:
     }
 #endif
 
+    void uct_forget(goal_ref const & g) {
+        expr * e;
+        unsigned touched_old, touched_new;
+
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            e = g->form(i);
+            touched_old = m_scores.find(e).touched;
+            touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
+            m_scores.find(e).touched = touched_new;
+            m_touched += touched_new - touched_old;
+        }
+    }
+
     void initialize(app * n) {
         // Build score table
         if (!m_scores.contains(n)) {
@@ -1195,6 +1209,8 @@ public:
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); 
 #elif _UCT_ == 2
                 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#elif _UCT_ == 3
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
                 if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
@@ -1202,7 +1218,7 @@ public:
             if (pos == static_cast<unsigned>(-1))
                 return m_temp_constants;
 
-#if _UCT_ == 1
+#if _UCT_ == 1 || _UCT_ == 3
             m_scores.find(g->form(pos)).touched++;
             m_touched++;
 #elif _UCT_ == 2
@@ -1343,6 +1359,8 @@ public:
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#elif _UCT_ == 3
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
             if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
@@ -1350,7 +1368,7 @@ public:
         if (pos == static_cast<unsigned>(-1))
             return 0;
 
-#if _UCT_ == 1
+#if _UCT_ == 1 || _UCT_ == 3
         m_scores.find(g->form(pos)).touched++;
         m_touched++;
 #elif _UCT_ == 2

From dfd2566e256d52cc3179137f3ee4f942d732d643 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 26 Mar 2014 17:26:06 +0000
Subject: [PATCH 042/108] removed dependency of bvsls on goal_refs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp  | 219 +++++++++++++++++++--------------
 src/tactic/sls/sls_engine.h    |  58 ++++-----
 src/tactic/sls/sls_evaluator.h |   4 +-
 src/tactic/sls/sls_tracker.h   |  84 ++++++-------
 4 files changed, 195 insertions(+), 170 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 92471aad8..9fa2cc263 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -74,15 +74,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
+bool sls_engine::full_eval(model & mdl) {
     bool res = true;
 
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(g->form(i), o, true))
+        if (!mdl.eval(m_assertions[i], o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -93,7 +93,7 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     return res;
 }
 
-double sls_engine::top_score(goal_ref const & g) {
+double sls_engine::top_score() {
 #if 0
     double min = m_tracker.get_score(g->form(0));
     unsigned sz = g->size();
@@ -108,15 +108,15 @@ double sls_engine::top_score(goal_ref const & g) {
     return min;
 #else
     double top_sum = 0.0;
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = g->form(i);
+        expr * e = m_assertions[i];
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(g->form(i));
+        tout << " " << m_tracker.get_score(m_assertions[i]);
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
 #if _CACHE_TOP_SCORE_
@@ -127,40 +127,40 @@ double sls_engine::top_score(goal_ref const & g) {
 #endif
 }
 
-double sls_engine::rescore(goal_ref const & g) {
+double sls_engine::rescore() {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score(g);
+    return top_score();
 }
 
-double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
+    return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-    return top_score(g);
+    return top_score();
 #endif
 }
 
-double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
+    return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-    return top_score(g);
+    return top_score();
 #endif
 }
 
-double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
 #if _EARLY_PRUNE_
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-        return (m_tracker.get_top_sum() / g->size());
+        return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-        return top_score(g);
+        return top_score();
 #endif
     else
         return 0.0;
@@ -170,8 +170,13 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c
 }
 
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if(
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
@@ -179,9 +184,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 #endif
 
 #if _EARLY_PRUNE_
-    double r = incremental_score_prune(g, fd, temp);
+    double r = incremental_score_prune(fd, temp);
 #else
-    double r = incremental_score(g, fd, temp);
+    double r = incremental_score(fd, temp);
 #endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
@@ -202,8 +207,15 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 }
 
 // same as what_if, but only applied to the score of a specific atom, not the total score
-bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                    double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if_local(
+    expr * e, 
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) 
+{
     m_evaluator.update(fd, temp);
     double r = m_tracker.get_score(e);
     if (r >= best_score) {
@@ -344,13 +356,19 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     m_mpz_manager.del(new_value);
 }
 
-void sls_engine::mk_random_move(goal_ref const & g) {
-    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
+void sls_engine::mk_random_move() {
+    mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves));
 }
 
 // will use VNS to ignore some possible moves and increase the flips per second
-double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move_vns(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
     unsigned bv_sz, max_bv_sz = 0;
     double new_score = score;
@@ -366,31 +384,31 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
             // try to flip lsb
             mk_flip(srt, old_value, 0, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = 0;
                 move = MV_FLIP;
             }
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         SASSERT(check == score);
     }
 
@@ -412,13 +430,13 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
                 {
                     mk_flip(srt, old_value, j, temp);
 
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                    if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                         new_bit = j;
                         move = MV_FLIP;
                     }
                 }
                 // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
+                double check = incremental_score(fd, old_value);
                 SASSERT(check == score);
             }
     m_mpz_manager.del(old_value);
@@ -427,8 +445,14 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
 }
 
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
     mpz temp2;
@@ -451,7 +475,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
@@ -462,19 +486,19 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
 #if _USE_UNARY_MINUS_
@@ -504,7 +528,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         // Andreas: does not hold anymore now that we use top level score caching
         //SASSERT(check == score);
     }
@@ -572,15 +596,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_eva
 }
 
 // first try of intensification ... does not seem to be efficient
-bool sls_engine::handle_plateau(goal_ref const & g)
+bool sls_engine::handle_plateau()
 {
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
 #if _BFS_
     unsigned pos = m_stats.m_moves % sz;
 #else
     unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+    expr * e = m_tracker.get_unsat_assertion(sz, pos);
     if (!e)
         return 0;
 
@@ -634,10 +658,15 @@ bool sls_engine::handle_plateau(goal_ref const & g)
 }
 
 // what_if version needed in the context of 2nd intensification try, combining local and global score
-bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                double & best_score, mpz & best_value, unsigned i) {
-
-    double global_score = incremental_score(g, fd, temp);
+bool sls_engine::what_if(
+    expr * e, 
+    func_decl * fd, 
+    const mpz & temp,
+    double & best_score, 
+    mpz & best_value, 
+    unsigned i) 
+{
+    double global_score = incremental_score(fd, temp);
     double local_score = m_tracker.get_score(e);
     double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
@@ -651,7 +680,7 @@ bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz
 }
 
 // find_best_move version needed in the context of 2nd intensification try
-double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i)
 {
     mpz old_value, temp;
     double best_score = 0;
@@ -662,7 +691,7 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl
 
     for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
         mk_flip(srt, old_value, j, temp);
-        what_if(g, e, fd, temp, best_score, best_value, i);
+        what_if(e, fd, temp, best_score, best_value, i);
     }
 
     m_mpz_manager.del(old_value);
@@ -672,15 +701,15 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl
 }
 
 // second try to use intensification ... also not very effective
-bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
+bool sls_engine::handle_plateau(double old_score)
 {
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
 #if _BFS_
     unsigned new_const = m_stats.m_moves % sz;
 #else
     unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+    expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const);
     if (!e)
         return 0;
 
@@ -697,12 +726,12 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 
     for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
     {
-        new_score = find_best_move_local(g, q, fd, new_value, i);
+        new_score = find_best_move_local(q, fd, new_value, i);
 
         m_stats.m_moves++;
         m_stats.m_flips++;
 
-        global_score = incremental_score(g, fd, new_value);
+        global_score = incremental_score(fd, new_value);
         local_score = m_tracker.get_score(q);
 
         SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
@@ -715,7 +744,7 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 }
 
 // main search loop
-lbool sls_engine::search(goal_ref const & g) {
+lbool sls_engine::search() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
@@ -723,8 +752,8 @@ lbool sls_engine::search(goal_ref const & g) {
     move_type move;
     unsigned plateau_cnt = 0;
 
-    score = rescore(g);
-    unsigned sz = g->size();
+    score = rescore();
+    unsigned sz = m_assertions.size();
 #if _PERC_STICKY_
     expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
@@ -750,7 +779,7 @@ lbool sls_engine::search(goal_ref const & g) {
         if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
             e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #else
-        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+        expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves);
 #endif
         if (!e)
         {
@@ -793,7 +822,7 @@ lbool sls_engine::search(goal_ref const & g) {
 #if _VNS_
         score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
 
         if (new_const == static_cast<unsigned>(-1)) {
@@ -811,14 +840,14 @@ lbool sls_engine::search(goal_ref const & g) {
             else
 #endif
 #if _REPICK_
-                m_evaluator.randomize_local(g, m_stats.m_moves);
+                m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
 #else
                 m_evaluator.randomize_local(to_evaluate);
 #endif
 #endif
 
 #if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / g->size();
+            score = m_tracker.get_top_sum() / m_assertions.size();
 #else
             score = top_score(g);
 #endif
@@ -828,7 +857,7 @@ lbool sls_engine::search(goal_ref const & g) {
 #if _REAL_RS_ || _REAL_PBFS_
             score = serious_score(g, fd, new_value);
 #else
-            score = incremental_score(g, fd, new_value);
+            score = incremental_score(fd, new_value);
 #endif
         }
     }
@@ -840,18 +869,18 @@ bailout:
 }
 
 // main search loop
-lbool sls_engine::search_old(goal_ref const & g) {
+lbool sls_engine::search_old() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
     mpz new_value;
     move_type move;
 
-    score = rescore(g);
+    score = rescore();
     TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
     tout << "Score distribution:";
-    for (unsigned i = 0; i < g->size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    for (unsigned i = 0; i < m_assertions.size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
     tout << " TOP: " << score << std::endl;);
 
     unsigned plateau_cnt = 0;
@@ -897,7 +926,7 @@ lbool sls_engine::search_old(goal_ref const & g) {
             old_score = score;
             new_const = (unsigned)-1;
 
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves);
             if (!to_evaluate.size())
             {
                 res = l_true;
@@ -908,22 +937,22 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 tout << to_evaluate[i]->get_name() << std::endl;);
 
 #if _VNS_
-            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
             if (new_const == static_cast<unsigned>(-1)) {
                 TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++) {
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                for (unsigned i = 0; i < m_assertions.size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
+                        tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl;
                 });
 
                 TRACE("sls_max", m_tracker.show_model(tout);
                 tout << "Scores: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
-                    m_tracker.get_score(g->form(i)) << std::endl;);
+                for (unsigned i = 0; i < m_assertions.size(); i++)
+                    tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " <<
+                    m_tracker.get_score(m_assertions[i]) << std::endl;);
                 // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                 score = old_score;
             }
@@ -962,14 +991,14 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 }
 
 #if _REAL_RS_ || _REAL_PBFS_
-                score = serious_score(g, fd, new_value);
+                score = serious_score(fd, new_value);
 #else
-                score = incremental_score(g, fd, new_value);
+                score = incremental_score(fd, new_value);
 #endif
 
                 TRACE("sls", tout << "Score distribution:";
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                for (unsigned i = 0; i < m_assertions.size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
                 tout << " TOP: " << score << std::endl;);
             }
 
@@ -978,8 +1007,8 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 // score could theoretically be imprecise.
                 // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                 bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1010,17 +1039,17 @@ lbool sls_engine::search_old(goal_ref const & g) {
             TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
 #if _INTENSIFICATION_
             handle_plateau(g, score);
-            //handle_plateau(g);
+            //handle_plateau();
 #else
-            m_evaluator.randomize_local(g, m_stats.m_moves);
+            m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
 #endif
-            //mk_random_move(g);
-            score = top_score(g);
+            //mk_random_move();
+            score = top_score();
 
             if (score >= 1.0) {
                 bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1046,6 +1075,10 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
+    for (unsigned i = 0; i < g->size(); i++)
+        assert_expr(g->form(i));
+    
+
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
     verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
@@ -1089,7 +1122,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 #if _WEIGHT_TOGGLE_
     m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
 #endif
-    m_tracker.initialize(g);
+    m_tracker.initialize(m_assertions);
     lbool res = l_undef;
 
     m_restart_limit = _RESTART_LIMIT_;
@@ -1098,14 +1131,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         checkpoint();
 
         report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search(g);
+        res = search();
 
         if (res == l_undef)
         {
 #if _RESTART_INIT_
-            m_tracker.randomize(g);
+            m_tracker.randomize();
 #else
-            m_tracker.reset(g);
+            m_tracker.reset(m_assertions);
 #endif
         }
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 878354c6d..8458817b6 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -71,6 +71,7 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
+    ptr_vector<expr> m_assertions;
 
     unsigned		m_restart_limit;
     unsigned        m_max_restarts;
@@ -92,11 +93,12 @@ public:
 
     void updt_params(params_ref const & _p);
 
+    void assert_expr(expr * e) { m_assertions.push_back(e); }
+
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(goal_ref const & g, model & mdl);
-    
+    bool full_eval(model & mdl);
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
     void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
@@ -104,54 +106,44 @@ public:
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
-    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    
-    
-    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                 double & best_score, mpz & best_value, unsigned i);
-    
-    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
-    
-
-    lbool search(goal_ref const & g);    
+    lbool search(void);    
 
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
-    lbool search_old(goal_ref const & g);
+    lbool search_old(void);
     double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
-
+    bool what_if(expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
     bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                        double & best_score, unsigned & best_const, mpz & best_value);
 
-    double top_score(goal_ref const & g);
-    double rescore(goal_ref const & g);
-    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
-    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double top_score();
+    double rescore();
+    double serious_score(func_decl * fd, const mpz & new_value);
+    double incremental_score(func_decl * fd, const mpz & new_value);
 
 #if _EARLY_PRUNE_
-    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score_prune(func_decl * fd, const mpz & new_value);
 #endif
-
-    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-
+    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
+    double find_best_move_vns(ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
-    void mk_random_move(goal_ref const & g);
+    void mk_random_move();
 
-    bool handle_plateau(goal_ref const & g);
-    bool handle_plateau(goal_ref const & g, double old_score);
+    bool handle_plateau(void);
+    bool handle_plateau(double old_score);
 
     inline unsigned check_restart(unsigned curr_value);
 };
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 9daf93c32..7638ba5f4 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -922,8 +922,8 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-     void randomize_local(goal_ref const & g, unsigned int flip) {
-        randomize_local(m_tracker.get_unsat_constants(g, flip));
+    void randomize_local(ptr_vector<expr> const & as, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(as, flip));
     } 
 };
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 1c33d42a7..c49257692 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,7 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"goal.h"
+#include"bv_decl_plugin.h"
 #include"model.h"
 
 #include"sls_compilation_settings.h"
@@ -365,12 +365,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(goal_ref const & g) {
+    void calculate_expr_distances(ptr_vector<expr> const & as) {
         // precondition: m_scores is set up.
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(g->form(i)));
+            stack.push_back(to_app(as[i]));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -418,12 +418,12 @@ public:
         quick_for_each_expr(ffd_proc, visited, e);
     }
 
-    void initialize(goal_ref const & g) {
+    void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
             else
@@ -438,7 +438,7 @@ public:
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
             initialize_recursive(e);
@@ -450,7 +450,7 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(g);
+        calculate_expr_distances(as);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
@@ -465,11 +465,11 @@ public:
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-            setup_occs(g->form(i));
+            setup_occs(as[i]);
 #endif
 
 #if _UCT_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
 #endif
     }
 
@@ -606,7 +606,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(goal_ref const & g) {
+    void randomize(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -620,13 +620,13 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
+        for (unsigned i = 0; i < as.size(); i++)
+            m_scores.find(as[i]).touched = 1;
 #endif
     }              
 
-    void reset(goal_ref const & g) {
+    void reset(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -636,9 +636,9 @@ public:
         }
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
+        for (unsigned i = 0; i < as.size(); i++)
+            m_scores.find(as[i]).touched = 1;
 #endif
     }              
 
@@ -1029,13 +1029,13 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as, unsigned sz) {
         if (sz == 1)
             return get_constants();
         m_temp_constants.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * q = g->form(i);
+            expr * q = as[i];
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -1049,22 +1049,22 @@ public:
         return m_temp_constants;
     }
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
             for (unsigned i = pos; i < sz; i++) {
-                expr * q = g->form(i);
+                expr * q = as[i];
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
+                expr * q = as[i];
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             return 0;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-            expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(as, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
             if (!q)
                 return m_temp_constants;
@@ -1141,19 +1141,19 @@ public:
             return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-        expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(as, sz, pos);
         if (!q)
             return m_temp_constants;
 
         return go_deeper(q);
     }
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
+    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as, unsigned int flip) {
+        unsigned sz = as.size();
 
         if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            if (m_mpz_manager.eq(get_value(as[0]), m_one))
                 return m_temp_constants;
             else
                 return get_constants();
@@ -1201,7 +1201,7 @@ public:
 #else
             double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1219,12 +1219,12 @@ public:
                 return m_temp_constants;
 
 #if _UCT_ == 1 || _UCT_ == 3
-            m_scores.find(g->form(pos)).touched++;
+            m_scores.find(as[pos]).touched++;
             m_touched++;
 #elif _UCT_ == 2
-            m_scores.find(g->form(pos)).touched = flip; 
+            m_scores.find(as[pos]).touched = flip; 
 #endif
-            expr * e = g->form(pos);
+            expr * e = as[pos];
 //            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
@@ -1303,11 +1303,11 @@ public:
     }
     
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
+    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned int flip) {
+        unsigned sz = as.size();
 
         if (sz == 1)
-            return g->form(0);
+            return as[0];
 
         m_temp_constants.reset();
 #if _FOCUS_ == 1
@@ -1351,7 +1351,7 @@ public:
 #else
         double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1369,13 +1369,13 @@ public:
             return 0;
 
 #if _UCT_ == 1 || _UCT_ == 3
-        m_scores.find(g->form(pos)).touched++;
+        m_scores.find(as[pos]).touched++;
         m_touched++;
 #elif _UCT_ == 2
         m_scores.find(g->form(pos)).touched = flip; 
 #endif
 //        return m_list_false[pos];
-        return g->form(pos);
+        return as[pos];
 
 #elif _BFS_ == 3
         unsigned int pos = -1;
@@ -1429,7 +1429,7 @@ public:
         unsigned int pos = get_random_uint(16) % sz;
         return get_unsat_assertion(g, sz, pos);
 #endif
-        return g->form(pos);
+        return as[pos];
 #elif _FOCUS_ == 2
 #if _BFS_
         unsigned int pos = flip % sz;

From e9482a1447bcc552521fa5b9851b79f707629ec1 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 27 Mar 2014 13:34:21 +0000
Subject: [PATCH 043/108] disabled old code

---
 src/tactic/sls/sls_engine.cpp | 4 +++-
 src/tactic/sls/sls_engine.h   | 3 +--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 9fa2cc263..cc06e4f78 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -868,6 +868,7 @@ bailout:
     return res;
 }
 
+#if 0 // Old code.
 // main search loop
 lbool sls_engine::search_old() {
     lbool res = l_undef;
@@ -1060,6 +1061,7 @@ lbool sls_engine::search_old() {
             }
         }
     }
+#endif
 
 bailout:
     m_mpz_manager.del(new_value);
@@ -1190,4 +1192,4 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         return 0;
     }
     return 1;
-}
\ No newline at end of file
+}
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8458817b6..5d4c9a0fc 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -114,7 +114,6 @@ public:
 
 protected:
     void checkpoint();
-    lbool search_old(void);
     double get_restart_armin(unsigned cnt_restarts);    
 
     bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
@@ -148,4 +147,4 @@ protected:
     inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
\ No newline at end of file
+#endif

From cf1a600fb981bfae72dd895e9fef9a9f79f3c5fb Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 27 Mar 2014 13:37:04 +0000
Subject: [PATCH 044/108] bugfix

---
 src/tactic/sls/sls_engine.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index cc06e4f78..10aaf6601 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1061,13 +1061,13 @@ lbool sls_engine::search_old() {
             }
         }
     }
-#endif
 
 bailout:
     m_mpz_manager.del(new_value);
 
     return res;
 }
+#endif
 
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {

From beef8198a42b18ce5d5f86df0729c2c0b5628a48 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:27:06 +0000
Subject: [PATCH 045/108] removed dependency of bvsls on goal_refs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index c49257692..cf1ad9ea3 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -276,13 +276,13 @@ public:
     }
 #endif
 
-    void uct_forget(goal_ref const & g) {
+    void uct_forget(ptr_vector<expr> & as) {
         expr * e;
         unsigned touched_old, touched_new;
 
-        for (unsigned i = 0; i < g->size(); i++)
+        for (unsigned i = 0; i < as.size(); i++)
         {
-            e = g->form(i);
+            e = as[i];
             touched_old = m_scores.find(e).touched;
             touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
             m_scores.find(e).touched = touched_new;

From ff7af2680de792f2ac1deacc84cb0687b9d48f14 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:28:40 +0000
Subject: [PATCH 046/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index cf1ad9ea3..fac080ee7 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,6 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
+#include"for_each_expr.h"
 #include"bv_decl_plugin.h"
 #include"model.h"
 

From 4e8c0c14188a0d1a315379cc0a42090f3c48f47c Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:30:15 +0000
Subject: [PATCH 047/108] compilation fixes

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.h  | 1 +
 src/tactic/sls/sls_tracker.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 5d4c9a0fc..96041d09e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,6 +22,7 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
+#include"goal.h"
 
 #include"sls_compilation_settings.h"
 #include"sls_tracker.h"
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index fac080ee7..537492213 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -21,6 +21,7 @@ Notes:
 #define _SLS_TRACKER_H_
 
 #include"for_each_expr.h"
+#include"ast_smt2_pp.h"
 #include"bv_decl_plugin.h"
 #include"model.h"
 

From c541694f403cd185f6ec09f8e5ab6c3fb149cdd4 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 14:58:59 +0000
Subject: [PATCH 048/108] bvsls refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 21 ++++++++++++---------
 src/tactic/sls/sls_engine.h   |  2 ++
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 10aaf6601..e7ee2abbd 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1069,6 +1069,16 @@ bailout:
 }
 #endif
 
+void sls_engine::init_tracker() {
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(m_assertions);
+}
+
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {
         mc = 0;
@@ -1078,8 +1088,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     m_produce_models = g->models_enabled();
 
     for (unsigned i = 0; i < g->size(); i++)
-        assert_expr(g->form(i));
-    
+        assert_expr(g->form(i));    
 
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
@@ -1118,13 +1127,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
     verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-#if _WEIGHT_DIST_ == 4
-    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-    m_tracker.initialize(m_assertions);
+    init_tracker();
     lbool res = l_undef;
 
     m_restart_limit = _RESTART_LIMIT_;
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 96041d09e..c56d6ec40 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -109,6 +109,8 @@ public:
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
     void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
+    void init_tracker(void);
+
     lbool search(void);    
 
     void operator()(goal_ref const & g, model_converter_ref & mc);

From 239849957a9f120994b453c1f4fa4ff5df3d7c10 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 15:26:52 +0000
Subject: [PATCH 049/108] bvsls refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 44 +++++++++++++++++++----------------
 src/tactic/sls/sls_engine.h   |  1 +
 2 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index e7ee2abbd..2b359608a 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1125,8 +1125,31 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
     verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;    
 
+    lbool res = operator()();
+
+    if (res == l_true) {
+        report_tactic_progress("Number of flips:", m_stats.m_moves);
+        for (unsigned i = 0; i < g->size(); i++)
+            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+            {
+                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                NOT_IMPLEMENTED_YET();
+            }
+
+        if (m_produce_models) {
+            model_ref mdl = m_tracker.get_model();
+            mc = model2model_converter(mdl.get());
+            TRACE("sls_model", mc->display(tout););
+        }
+        g->reset();
+    }
+    else
+        mc = 0;
+}
+
+lbool sls_engine::operator()() {
     init_tracker();
     lbool res = l_undef;
 
@@ -1149,25 +1172,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
 
     verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-    if (res == l_true) {
-        report_tactic_progress("Number of flips:", m_stats.m_moves);
-        for (unsigned i = 0; i < g->size(); i++)
-            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-            {
-                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                NOT_IMPLEMENTED_YET();
-            }
-
-        if (m_produce_models) {
-            model_ref mdl = m_tracker.get_model();
-            mc = model2model_converter(mdl.get());
-            TRACE("sls_model", mc->display(tout););
-        }
-        g->reset();
-    }
-    else
-        mc = 0;
 }
 
 unsigned sls_engine::check_restart(unsigned curr_value)
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index c56d6ec40..c6e3af155 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -113,6 +113,7 @@ public:
 
     lbool search(void);    
 
+    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:

From f88b034b8b04e27773a5e2c476fe52884a3cd56d Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 15:28:02 +0000
Subject: [PATCH 050/108] bvsls bugfix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 2b359608a..dc4451bb5 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1172,6 +1172,8 @@ lbool sls_engine::operator()() {
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
 
     verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+    
+    return res;
 }
 
 unsigned sls_engine::check_restart(unsigned curr_value)

From 42702c8d8a9be639f3962cacc61bd3103cbe77f4 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Sun, 20 Apr 2014 16:38:49 +0100
Subject: [PATCH 051/108] Current version before integration ...

---
 src/tactic/sls/sls_compilation_settings.h |  40 +-
 src/tactic/sls/sls_engine.cpp             | 586 +++++++++++++++-------
 src/tactic/sls/sls_engine.h               |  73 +--
 src/tactic/sls/sls_evaluator.h            | 152 +++++-
 src/tactic/sls/sls_tactic.cpp             |   4 +-
 src/tactic/sls/sls_tracker.h              | 472 ++++++++++++++---
 src/tactic/smtlogics/qfbv_tactic.cpp      |  28 ++
 7 files changed, 1068 insertions(+), 287 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 8e52596e0..d2b899dd8 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -36,17 +36,21 @@ Notes:
 // do we use dirty unit propagation to get rid of nested top level assertions?
 #define _DIRTY_UP_ 0
 
+// shall we use additive weighting scheme?
+#define _PAWS_ 5
+#define _PAWS_INIT_ 40
+
 // do we use restarts?
 // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
+#define _RESTARTS_ 1
 // limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
+#define _RESTART_LIMIT_ 100
 // 0 = initialize with all zero, 1 initialize with random value
 #define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
 #define _RESTART_SCHEME_ 1
 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 3.0
+#define _RESTART_CONST_ARMIN_ 2.0
 
 // timelimit
 #define _TIMELIMIT_ 3600
@@ -61,6 +65,21 @@ Notes:
 // 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
 #define _VNS_ 0
 
+// shall we check 2-bit flips in plateaus using Monte Carlo?
+#define _VNS_MC_ 0
+
+// how many 2-bit flips shall we try per bit?
+#define _VNS_MC_TRIES_ 1
+
+// shall we check another assertion if no improving step was found in the first one?
+#define _VNS_REPICK_ 0
+
+// what is the probability of doing so (percentage)?
+#define _VNS_PERC_ 100
+
+// do a decreasing move with percentage ...
+#define _INSIST_PERC_ 0
+
 // do we reduce the score of unsatisfied literals?
 // 0 = no
 // 1 = yes, by multiplying it with some factor
@@ -70,7 +89,7 @@ Notes:
 #define _WEIGHT_DIST_ 1
 
 // the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.25
+#define _WEIGHT_DIST_FACTOR_ 0.5
 
 // shall we toggle the weight after each restart?
 #define _WEIGHT_TOGGLE_ 0
@@ -82,14 +101,15 @@ Notes:
 // what is the percentage of random moves in plateaus (instead of full randomization)?
 #define _PERC_PLATEAU_MOVES_ 0
 
-// shall we repick clause when randomizing in a plateau or use the current one?
+// shall we repick assertion when randomizing in a plateau or use the current one?
+// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one
 #define _REPICK_ 1
 
 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_
 #define _UCT_ 1
 
 // how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 10.0
+#define _UCT_CONSTANT_ 20.0
 
 // is uct clause selection probabilistic similar to variable selection in sparrow?
 // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
@@ -103,7 +123,11 @@ Notes:
 
 // how shall we initialize the _UCT_ total touched counter?
 // 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 1
+#define _UCT_INIT_ 0
+
+// do we gradually reduce the touched values of _UCT_?
+#define _UCT_FORGET_ 0
+#define _UCT_FORGET_FACTOR_ 0.9
 
 // shall we use addition/subtraction?
 #define _USE_ADDSUB_ 1
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index dc4451bb5..342e649af 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -74,15 +74,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(model & mdl) {
+bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     bool res = true;
 
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(m_assertions[i], o, true))
+        if (!mdl.eval(g->form(i), o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -93,7 +93,7 @@ bool sls_engine::full_eval(model & mdl) {
     return res;
 }
 
-double sls_engine::top_score() {
+double sls_engine::top_score(goal_ref const & g) {
 #if 0
     double min = m_tracker.get_score(g->form(0));
     unsigned sz = g->size();
@@ -108,15 +108,15 @@ double sls_engine::top_score() {
     return min;
 #else
     double top_sum = 0.0;
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = m_assertions[i];
+        expr * e = g->form(i);
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(m_assertions[i]);
+        tout << " " << m_tracker.get_score(g->form(i));
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
 #if _CACHE_TOP_SCORE_
@@ -127,40 +127,40 @@ double sls_engine::top_score() {
 #endif
 }
 
-double sls_engine::rescore() {
+double sls_engine::rescore(goal_ref const & g) {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score();
+    return top_score(g);
 }
 
-double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return (m_tracker.get_top_sum() / g->size());
 #else
-    return top_score();
+    return top_score(g);
 #endif
 }
 
-double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return (m_tracker.get_top_sum() / g->size());
 #else
-    return top_score();
+    return top_score(g);
 #endif
 }
 
-double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
 #if _EARLY_PRUNE_
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-        return (m_tracker.get_top_sum() / m_assertions.size());
+        return (m_tracker.get_top_sum() / g->size());
 #else
-        return top_score();
+        return top_score(g);
 #endif
     else
         return 0.0;
@@ -169,14 +169,17 @@ double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value
 #endif
 }
 
+double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+    m_stats.m_incr_evals++;
+    if (m_evaluator.update_prune_new(fd, new_value))
+        return (m_tracker.get_top_sum() / g->size());
+    else
+        return 0.0;
+}
+
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(
-    func_decl * fd, 
-    const unsigned & fd_inx, 
-    const mpz & temp,
-    double & best_score, 
-    unsigned & best_const, 
-    mpz & best_value) {
+bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
@@ -184,9 +187,9 @@ bool sls_engine::what_if(
 #endif
 
 #if _EARLY_PRUNE_
-    double r = incremental_score_prune(fd, temp);
+    double r = incremental_score_prune(g, fd, temp);
 #else
-    double r = incremental_score(fd, temp);
+    double r = incremental_score(g, fd, temp);
 #endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
@@ -195,8 +198,33 @@ bool sls_engine::what_if(
     m_mpz_manager.del(old_value);
 #endif
 
-    //            if (r >= best_score) {
+    //if (r >= best_score) {
     if (r > best_score) {
+        m_tracker.reset_equal_scores();
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+    /*else if (r == best_score) {
+        if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0)
+        {
+            best_score = r;
+            best_const = fd_inx;
+            m_mpz_manager.set(best_value, temp);
+            return true;
+        }
+    }*/
+
+    return false;
+}
+
+bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
+
+    double r = incremental_score_prune_new(g, fd, temp);
+
+    if (r >= best_score) {
         best_score = r;
         best_const = fd_inx;
         m_mpz_manager.set(best_value, temp);
@@ -207,15 +235,8 @@ bool sls_engine::what_if(
 }
 
 // same as what_if, but only applied to the score of a specific atom, not the total score
-bool sls_engine::what_if_local(
-    expr * e, 
-    func_decl * fd, 
-    const unsigned & fd_inx, 
-    const mpz & temp,
-    double & best_score, 
-    unsigned & best_const, 
-    mpz & best_value) 
-{
+bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                    double & best_score, unsigned & best_const, mpz & best_value) {
     m_evaluator.update(fd, temp);
     double r = m_tracker.get_score(e);
     if (r >= best_score) {
@@ -356,19 +377,13 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     m_mpz_manager.del(new_value);
 }
 
-void sls_engine::mk_random_move() {
-    mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves));
+void sls_engine::mk_random_move(goal_ref const & g) {
+    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
 }
 
 // will use VNS to ignore some possible moves and increase the flips per second
-double sls_engine::find_best_move_vns(
-    ptr_vector<func_decl> & to_evaluate, 
-    double score,
-    unsigned & best_const, 
-    mpz & best_value, 
-    unsigned & new_bit, 
-    move_type & move) 
-{
+double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
     mpz old_value, temp;
     unsigned bv_sz, max_bv_sz = 0;
     double new_score = score;
@@ -384,31 +399,31 @@ double sls_engine::find_best_move_vns(
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(fd, i, temp, new_score, best_const, best_value))
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
             // try to flip lsb
             mk_flip(srt, old_value, 0, temp);
-            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = 0;
                 move = MV_FLIP;
             }
         }
 
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
+        double check = incremental_score(g, fd, old_value);
         SASSERT(check == score);
     }
 
@@ -430,13 +445,13 @@ double sls_engine::find_best_move_vns(
                 {
                     mk_flip(srt, old_value, j, temp);
 
-                    if (what_if(fd, i, temp, new_score, best_const, best_value)) {
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
                         new_bit = j;
                         move = MV_FLIP;
                     }
                 }
                 // reset to what it was before
-                double check = incremental_score(fd, old_value);
+                double check = incremental_score(g, fd, old_value);
                 SASSERT(check == score);
             }
     m_mpz_manager.del(old_value);
@@ -444,23 +459,99 @@ double sls_engine::find_best_move_vns(
     return new_score;
 }
 
+double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+    unsigned bv_sz, max_bv_sz = 0;
+    double new_score = score;
+
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+
+            // try to flip lsb
+            mk_flip(srt, old_value, 0, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = 0;
+                move = MV_FLIP;
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        SASSERT(check == score);
+    }
+
+    for (unsigned j = 1; j < max_bv_sz; j++)
+    {
+        for (unsigned i = 0; i < to_evaluate.size(); i++) {
+            func_decl * fd = to_evaluate[i];
+            sort * srt = fd->get_range();
+            bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+            // What would happen if we flipped bit #j ?                
+            if (j < bv_sz)
+            {
+                mk_flip(srt, old_value, j, temp);
+
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                    new_bit = j;
+                    move = MV_FLIP;
+                }
+            }
+            // reset to what it was before
+            double check = incremental_score(g, fd, old_value);
+            SASSERT(check == score);
+        }
+    }
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(
-    ptr_vector<func_decl> & to_evaluate, 
-    double score,
-    unsigned & best_const, 
-    mpz & best_value, 
-    unsigned & new_bit, 
-    move_type & move) 
-{
+double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
     mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
     mpz temp2;
 #endif
     unsigned bv_sz;
+#if _INSIST_PERC_
+    double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score;
+#else
     double new_score = score;
+#endif
 
-    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    m_tracker.reset_equal_scores();
+
+//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+//    for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) {
+//    for (unsigned i = to_evaluate.size(); i-- > 0; ) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -470,15 +561,28 @@ double sls_engine::find_best_move(
 #if _SKIP_BITS_
         for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
 #else
-        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+//        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+        for (unsigned j = 0; j < bv_sz; j++) {
+//        for (unsigned j = bv_sz; j-- > 0; ) {
 #endif
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
+            //if (m_tracker.get_random_uint(1))
+            //if ((move != MV_FLIP) || (new_bit > j))
+            //{
+            //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) {
+            //    new_bit = j;
+            //    move = MV_FLIP;
+            //}
+            //}
+            //else
+            //{
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
+            //}
         }
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -486,19 +590,22 @@ double sls_engine::find_best_move(
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                //if (m_tracker.get_random_uint(1))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                //if (m_tracker.get_random_uint(1))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(fd, i, temp, new_score, best_const, best_value))
+            //if (m_tracker.get_random_uint(1))
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
 #if _USE_UNARY_MINUS_
@@ -528,7 +635,7 @@ double sls_engine::find_best_move(
         }
 
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
+        double check = incremental_score(g, fd, old_value);
         // Andreas: does not hold anymore now that we use top level score caching
         //SASSERT(check == score);
     }
@@ -538,6 +645,50 @@ double sls_engine::find_best_move(
 #if _USE_MUL3_
     m_mpz_manager.del(temp2);
 #endif
+
+    if ((new_score == score) && 1)// (m_tracker.get_random_uint(1)))
+        best_const = -1;
+
+    return new_score;
+}
+
+// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value) {
+    mpz old_value, temp, temp2;
+    unsigned bv_sz;
+    double new_score = score;
+
+//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) {
+//            for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+            for (unsigned j = 0; j < bv_sz; j++) {
+                mk_flip(srt, old_value, j, temp);
+                for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++)
+                {
+                    unsigned k = m_tracker.get_random_uint(16) % bv_sz;
+                    while (k == j)
+                        k = m_tracker.get_random_uint(16) % bv_sz;
+                    mk_flip(srt, temp, k, temp2);
+                    what_if(g, fd, i, temp2, new_score, best_const, best_value);
+                }
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(temp2);
+
     return new_score;
 }
 
@@ -596,15 +747,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_eva
 }
 
 // first try of intensification ... does not seem to be efficient
-bool sls_engine::handle_plateau()
+bool sls_engine::handle_plateau(goal_ref const & g)
 {
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
 #if _BFS_
     unsigned pos = m_stats.m_moves % sz;
 #else
     unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(sz, pos);
+    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
     if (!e)
         return 0;
 
@@ -658,15 +809,10 @@ bool sls_engine::handle_plateau()
 }
 
 // what_if version needed in the context of 2nd intensification try, combining local and global score
-bool sls_engine::what_if(
-    expr * e, 
-    func_decl * fd, 
-    const mpz & temp,
-    double & best_score, 
-    mpz & best_value, 
-    unsigned i) 
-{
-    double global_score = incremental_score(fd, temp);
+bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                double & best_score, mpz & best_value, unsigned i) {
+
+    double global_score = incremental_score(g, fd, temp);
     double local_score = m_tracker.get_score(e);
     double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
@@ -680,7 +826,7 @@ bool sls_engine::what_if(
 }
 
 // find_best_move version needed in the context of 2nd intensification try
-double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i)
+double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
 {
     mpz old_value, temp;
     double best_score = 0;
@@ -691,7 +837,7 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val
 
     for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
         mk_flip(srt, old_value, j, temp);
-        what_if(e, fd, temp, best_score, best_value, i);
+        what_if(g, e, fd, temp, best_score, best_value, i);
     }
 
     m_mpz_manager.del(old_value);
@@ -701,15 +847,15 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val
 }
 
 // second try to use intensification ... also not very effective
-bool sls_engine::handle_plateau(double old_score)
+bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 {
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
 #if _BFS_
     unsigned new_const = m_stats.m_moves % sz;
 #else
     unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const);
+    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
     if (!e)
         return 0;
 
@@ -726,12 +872,12 @@ bool sls_engine::handle_plateau(double old_score)
 
     for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
     {
-        new_score = find_best_move_local(q, fd, new_value, i);
+        new_score = find_best_move_local(g, q, fd, new_value, i);
 
         m_stats.m_moves++;
         m_stats.m_flips++;
 
-        global_score = incremental_score(fd, new_value);
+        global_score = incremental_score(g, fd, new_value);
         local_score = m_tracker.get_score(q);
 
         SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
@@ -744,7 +890,7 @@ bool sls_engine::handle_plateau(double old_score)
 }
 
 // main search loop
-lbool sls_engine::search() {
+lbool sls_engine::search(goal_ref const & g) {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
@@ -752,8 +898,15 @@ lbool sls_engine::search() {
     move_type move;
     unsigned plateau_cnt = 0;
 
-    score = rescore();
-    unsigned sz = m_assertions.size();
+    score = rescore(g);
+    unsigned sz = g->size();
+
+    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+    tout << "Score distribution:";
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    tout << " TOP: " << score << std::endl;);
+
 #if _PERC_STICKY_
     expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
@@ -767,9 +920,18 @@ lbool sls_engine::search() {
 #else
     while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
 #endif
+        //if (m_stats.m_stopwatch.get_current_seconds() > 10.0)
+        //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);}
+
         checkpoint();
         m_stats.m_moves++;
 
+#if _UCT_FORGET_
+        //if (m_stats.m_moves % sz == 0)
+        if (m_stats.m_moves % _UCT_FORGET_ == 0)
+            m_tracker.uct_forget(g);
+#endif
+
 #if _REAL_RS_ || _REAL_PBFS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
@@ -779,13 +941,14 @@ lbool sls_engine::search() {
         if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
             e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #else
-        expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves);
+        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
         if (!e)
         {
             res = l_true;
             goto bailout;
         }
+        //ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_only(e);
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
 #else
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
@@ -818,13 +981,69 @@ lbool sls_engine::search() {
 #endif       
         old_score = score;
         new_const = (unsigned)-1;
+        move = MV_FLIP;
+        new_bit = 0;
 
 #if _VNS_
         score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
+        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
 
+#if _VNS_MC_ > _VNS_REPICK_
+#if _VNS_MC_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+#endif
+#if _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+#endif
+#endif
+
+#if _VNS_MC_ < _VNS_REPICK_
+#if _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+#endif
+#if _VNS_MC_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+#endif
+#endif
+
+#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1)) {
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+            else {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+        }        
+#endif
+
+
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
             plateau_cnt++;
@@ -839,25 +1058,52 @@ lbool sls_engine::search() {
                 mk_random_move(to_evaluate);
             else
 #endif
-#if _REPICK_
-                m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
+#if _REPICK_ == 1
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _REPICK_ == 2
+            {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                    m_evaluator.randomize_local(q);
+                else
+                    m_evaluator.randomize_local(e);
+            }
 #else
-                m_evaluator.randomize_local(to_evaluate);
+                m_evaluator.randomize_local_n(g, to_evaluate);
+                //m_evaluator.randomize_local(to_evaluate);
 #endif
 #endif
 
 #if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / m_assertions.size();
+            score = m_tracker.get_top_sum() / g->size();
 #else
             score = top_score(g);
 #endif
+
+#if _PAWS_
+            for (unsigned i = 0; i < sz; i++)
+            {
+                expr * q = g->form(i);
+                if (m_tracker.get_random_uint(16) % 100 < _PAWS_)
+                {
+                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
+                        m_tracker.decrease_weight(q);
+                }
+                else
+                {
+                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
+                        m_tracker.increase_weight(q);
+                }
+            }
+#endif
+
         }
         else {
             func_decl * fd = to_evaluate[new_const];
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
             score = serious_score(g, fd, new_value);
 #else
-            score = incremental_score(fd, new_value);
+            score = incremental_score(g, fd, new_value);
 #endif
         }
     }
@@ -868,20 +1114,19 @@ bailout:
     return res;
 }
 
-#if 0 // Old code.
 // main search loop
-lbool sls_engine::search_old() {
+lbool sls_engine::search_old(goal_ref const & g) {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
     mpz new_value;
     move_type move;
 
-    score = rescore();
+    score = rescore(g);
     TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
     tout << "Score distribution:";
-    for (unsigned i = 0; i < m_assertions.size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
     tout << " TOP: " << score << std::endl;);
 
     unsigned plateau_cnt = 0;
@@ -927,7 +1172,7 @@ lbool sls_engine::search_old() {
             old_score = score;
             new_const = (unsigned)-1;
 
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
             if (!to_evaluate.size())
             {
                 res = l_true;
@@ -938,22 +1183,22 @@ lbool sls_engine::search_old() {
                 tout << to_evaluate[i]->get_name() << std::endl;);
 
 #if _VNS_
-            score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-            score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
             if (new_const == static_cast<unsigned>(-1)) {
                 TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
-                for (unsigned i = 0; i < m_assertions.size(); i++) {
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
-                        tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl;
+                for (unsigned i = 0; i < g->size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
                 });
 
                 TRACE("sls_max", m_tracker.show_model(tout);
                 tout << "Scores: " << std::endl;
-                for (unsigned i = 0; i < m_assertions.size(); i++)
-                    tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " <<
-                    m_tracker.get_score(m_assertions[i]) << std::endl;);
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
+                    m_tracker.get_score(g->form(i)) << std::endl;);
                 // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                 score = old_score;
             }
@@ -991,15 +1236,15 @@ lbool sls_engine::search_old() {
                 case MV_DIV2: m_stats.m_div2s++; break;
                 }
 
-#if _REAL_RS_ || _REAL_PBFS_
-                score = serious_score(fd, new_value);
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
+                score = serious_score(g, fd, new_value);
 #else
-                score = incremental_score(fd, new_value);
+                score = incremental_score(g, fd, new_value);
 #endif
 
                 TRACE("sls", tout << "Score distribution:";
-                for (unsigned i = 0; i < m_assertions.size(); i++)
-                    tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
                 tout << " TOP: " << score << std::endl;);
             }
 
@@ -1008,8 +1253,8 @@ lbool sls_engine::search_old() {
                 // score could theoretically be imprecise.
                 // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                 bool all_true = true;
-                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1040,17 +1285,17 @@ lbool sls_engine::search_old() {
             TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
 #if _INTENSIFICATION_
             handle_plateau(g, score);
-            //handle_plateau();
+            //handle_plateau(g);
 #else
-            m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
+            m_evaluator.randomize_local(g, m_stats.m_moves);
 #endif
-            //mk_random_move();
-            score = top_score();
+            //mk_random_move(g);
+            score = top_score(g);
 
             if (score >= 1.0) {
                 bool all_true = true;
-                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1067,17 +1312,6 @@ bailout:
 
     return res;
 }
-#endif
-
-void sls_engine::init_tracker() {
-#if _WEIGHT_DIST_ == 4
-    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-    m_tracker.initialize(m_assertions);
-}
 
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {
@@ -1087,9 +1321,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
-    for (unsigned i = 0; i < g->size(); i++)
-        assert_expr(g->form(i));    
-
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
     verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
@@ -1100,7 +1331,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
     verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
     verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+    verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl;
+    verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl;
     verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+    verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl;
+    verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl;
+    verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl;
+    verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl;
+    verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl;
     verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
     verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
     verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
@@ -1111,6 +1349,8 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
     verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
     verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+    verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
+    verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
     verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
     verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
     verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
@@ -1125,9 +1365,36 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
     verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;    
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-    lbool res = operator()();
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(g);
+    lbool res = l_undef;
+
+    m_restart_limit = _RESTART_LIMIT_;
+
+    do {
+        checkpoint();
+
+        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+        res = search(g);
+
+        if (res == l_undef)
+        {
+#if _RESTART_INIT_
+            m_tracker.randomize(g);
+#else
+            m_tracker.reset(g);
+#endif
+        }
+    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+
+    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
 
     if (res == l_true) {
         report_tactic_progress("Number of flips:", m_stats.m_moves);
@@ -1149,38 +1416,13 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         mc = 0;
 }
 
-lbool sls_engine::operator()() {
-    init_tracker();
-    lbool res = l_undef;
-
-    m_restart_limit = _RESTART_LIMIT_;
-
-    do {
-        checkpoint();
-
-        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search();
-
-        if (res == l_undef)
-        {
-#if _RESTART_INIT_
-            m_tracker.randomize();
-#else
-            m_tracker.reset(m_assertions);
-#endif
-        }
-    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-
-    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-    
-    return res;
-}
-
 unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_limit)
     {
-#if _RESTART_SCHEME_ == 4
+#if _RESTART_SCHEME_ == 5
+        m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+#elif _RESTART_SCHEME_ == 4
         m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
         m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
@@ -1188,9 +1430,11 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
 #elif _RESTART_SCHEME_ == 1
         if (m_stats.m_restarts & 1)
+        //if (m_stats.m_restarts % 3 == 2)
             m_restart_limit += _RESTART_LIMIT_;
         else
             m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+            //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_;
 #else
         m_restart_limit += _RESTART_LIMIT_;
 #endif
@@ -1201,4 +1445,4 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         return 0;
     }
     return 1;
-}
+}
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index c6e3af155..902c6b7a0 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,7 +22,6 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
-#include"goal.h"
 
 #include"sls_compilation_settings.h"
 #include"sls_tracker.h"
@@ -72,7 +71,6 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
-    ptr_vector<expr> m_assertions;
 
     unsigned		m_restart_limit;
     unsigned        m_max_restarts;
@@ -94,12 +92,11 @@ public:
 
     void updt_params(params_ref const & _p);
 
-    void assert_expr(expr * e) { m_assertions.push_back(e); }
-
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(model & mdl);
+    bool full_eval(goal_ref const & g, model & mdl);
+    
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
     void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
@@ -107,48 +104,66 @@ public:
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
 
-    void init_tracker(void);
+    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
 
-    lbool search(void);    
+    double find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+
+    double find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value);
+
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    
+    
+    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
+    
+    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    
+
+    lbool search(goal_ref const & g);    
 
-    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
+    lbool search_old(goal_ref const & g);
     double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
-    bool what_if(expr * e, func_decl * fd, const mpz & temp,
-                 double & best_score, mpz & best_value, unsigned i);
+
+    bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                 double & best_score, unsigned & best_const, mpz & best_value);
+    double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value);
+
     bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                        double & best_score, unsigned & best_const, mpz & best_value);
 
-    double top_score();
-    double rescore();
-    double serious_score(func_decl * fd, const mpz & new_value);
-    double incremental_score(func_decl * fd, const mpz & new_value);
+    double top_score(goal_ref const & g);
+    double rescore(goal_ref const & g);
+    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
 
 #if _EARLY_PRUNE_
-    double incremental_score_prune(func_decl * fd, const mpz & new_value);
+    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
 #endif
-    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i);
-    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
-    double find_best_move_vns(ptr_vector<func_decl> & to_evaluate, double score,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
-    void mk_random_move(ptr_vector<func_decl> & unsat_constants);
-    void mk_random_move();
 
-    bool handle_plateau(void);
-    bool handle_plateau(double old_score);
+    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+
+    void mk_random_move(ptr_vector<func_decl> & unsat_constants);
+    void mk_random_move(goal_ref const & g);
+
+    bool handle_plateau(goal_ref const & g);
+    bool handle_plateau(goal_ref const & g, double old_score);
 
     inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 7638ba5f4..78f2cb79a 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -575,7 +575,7 @@ public:
 #if _CACHE_TOP_SCORE_
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
@@ -584,12 +584,13 @@ public:
                 new_score = m_tracker.score(cur);
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
+
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -634,7 +635,7 @@ public:
 #if _CACHE_TOP_SCORE_
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
@@ -643,12 +644,12 @@ public:
                 new_score = m_tracker.score(cur);
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -683,7 +684,7 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         run_serious_update(max_depth);
 #else
         run_update(max_depth);
@@ -729,14 +730,16 @@ public:
 #if _CACHE_TOP_SCORE_
             //if (!m_tracker.has_uplinks(cur))
             if (m_tracker.is_top_expr(cur))
-                m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
             prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
             if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+            //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
                 pot_benefits = 1;
             if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+            //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
                 pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
@@ -771,7 +774,7 @@ public:
                     new_score = m_tracker.score(cur); 
                     //if (!m_tracker.has_uplinks(cur))
                     if (m_tracker.is_top_expr(cur))
-                        m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
 #else
                     m_tracker.set_score(cur, m_tracker.score(cur));
@@ -858,6 +861,104 @@ public:
     }
 #endif
 
+    unsigned run_update_bool_prune_new(unsigned cur_depth) {
+        expr_fast_mark1 visited;
+
+        double prune_score, new_score;
+        unsigned pot_benefits = 0;
+        SASSERT(cur_depth < m_traversal_stack_bool.size());
+ 
+        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+
+        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+            expr * cur = cur_depth_exprs[i];
+
+            new_score = m_tracker.score(cur); 
+            //if (!m_tracker.has_uplinks(cur))
+            if (m_tracker.is_top_expr(cur))
+                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+            prune_score = m_tracker.get_score_prune(cur);
+            m_tracker.set_score(cur, new_score);
+
+            if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
+                pot_benefits = 1;
+            if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
+                pot_benefits = 1;
+
+            if (m_tracker.has_uplinks(cur)) {
+                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                for (unsigned j = 0; j < ups.size(); j++) {
+                    expr * next = ups[j];
+                    unsigned next_d = m_tracker.get_distance(next);
+                    SASSERT(next_d < cur_depth);
+                    if (!visited.is_marked(next)) {
+                        m_traversal_stack_bool[next_d].push_back(next);
+                        visited.mark(next);
+                    }
+                }
+            }
+            else
+            {
+            }
+        }
+
+        cur_depth_exprs.reset();
+        cur_depth--;
+ 
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+            if (pot_benefits)
+            {
+                unsigned cur_size = cur_depth_exprs.size();
+                for (unsigned i = 0; i < cur_size; i++) {
+                    expr * cur = cur_depth_exprs[i];
+
+                    new_score = m_tracker.score(cur); 
+                    //if (!m_tracker.has_uplinks(cur))
+                    if (m_tracker.is_top_expr(cur))
+                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                    m_tracker.set_score(cur, new_score);
+                    if (m_tracker.has_uplinks(cur)) {
+                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                        for (unsigned j = 0; j < ups.size(); j++) {
+                            expr * next = ups[j];
+                            unsigned next_d = m_tracker.get_distance(next);
+                            SASSERT(next_d < cur_depth);
+                            if (!visited.is_marked(next)) {
+                                m_traversal_stack_bool[next_d].push_back(next);
+                                visited.mark(next);
+                            }
+                        }
+                    }
+                }
+            }
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        return pot_benefits;
+    }
+
+    unsigned update_prune_new(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+
+        if (m_traversal_stack_bool.size() <= cur_depth)
+            m_traversal_stack_bool.resize(cur_depth+1);
+        if (m_traversal_stack.size() <= cur_depth) 
+                m_traversal_stack.resize(cur_depth+1);
+
+        if (m_manager.is_bool(ep))
+            m_traversal_stack_bool[cur_depth].push_back(ep);
+        else
+        {
+            m_traversal_stack[cur_depth].push_back(ep);
+            run_update_prune(cur_depth);
+        }
+        return run_update_bool_prune_new(cur_depth);
+    }
+
     void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _all_ candidates:
 
@@ -901,7 +1002,7 @@ public:
         mpz temp = m_tracker.get_random(fd->get_range());
 #endif
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         serious_update(fd, temp);
 #else
         update(fd, temp);
@@ -922,9 +1023,36 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-    void randomize_local(ptr_vector<expr> const & as, unsigned int flip) {
-        randomize_local(m_tracker.get_unsat_constants(as, flip));
+    void randomize_local(goal_ref const & g, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(g, flip));
     } 
+
+    void randomize_local_n(goal_ref const & g, ptr_vector<func_decl> & unsat_constants) {
+        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
+        func_decl * fd = unsat_constants[r];
+        sort * srt = fd->get_range();
+        unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); 
+        mpz max_val = m_tracker.get_random(srt);
+        update(fd, max_val);
+        double max_score = m_tracker.get_top_sum() / g->size();
+        mpz temp_val;
+        double temp_score;
+        for (unsigned i = 1; i < 2; i++)
+        //for (unsigned i = 1; i < bv_sz; i++)
+        {
+            m_mpz_manager.set(temp_val, m_tracker.get_random(srt));
+            update(fd, temp_val);
+            temp_score = m_tracker.get_top_sum() / g->size();
+            if (temp_score > max_score)
+            {
+                m_mpz_manager.set(max_val, temp_val);
+                max_score = temp_score;
+            }
+        }
+        update(fd, max_val);
+        m_mpz_manager.del(temp_val);
+        m_mpz_manager.del(max_val);
+    }
 };
 
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index b2b7035e0..0b6b01e7c 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -1509,14 +1509,14 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                         mk_max_bv_sharing_tactic(m),
                         // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
                         //mk_ctx_simplify_tactic(m, ctx_p),
-                        // Andreas: This one at least eliminates top level duplicates ...
+                        // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance!
                         //mk_simplify_tactic(m),
-                        // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
     tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
+//    tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 537492213..87c90f1f8 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,9 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"for_each_expr.h"
-#include"ast_smt2_pp.h"
-#include"bv_decl_plugin.h"
+#include"goal.h"
 #include"model.h"
 
 #include"sls_compilation_settings.h"
@@ -88,12 +86,17 @@ private:
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
 #endif
+#if _PAWS_
+    obj_map<expr, unsigned> m_weights;
+    //obj_map<expr, double> m_weights;
+#endif
 #if _CACHE_TOP_SCORE_
     double				  m_top_sum;
 #endif
 #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     double				  m_weight_dist_factor;
 #endif
+    unsigned              m_equal_scores;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -113,15 +116,52 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+    unsigned get_formula_size() {
+        return m_scores.size();
+    }
+
+    double get_avg_bw(goal_ref const & g) {
+        double sum = 0.0;
+        unsigned count = 0;
+
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            m_temp_constants.reset();
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(g->form(i));
+            unsigned sz = this_decls.size();
+            for (unsigned i = 0; i < sz; i++) {
+                func_decl * fd = this_decls[i];
+                m_temp_constants.push_back(fd);
+                sort * srt = fd->get_range();
+                sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);         
+                count++;
+            }
+        }
+
+        return sum / count;   
+    }
+
 #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     inline void set_weight_dist_factor(double val) {
         m_weight_dist_factor = val;
     }
 #endif
 
+    void reset_equal_scores() {
+        m_equal_scores = 1;
+    }
+
+    unsigned inc_equal_scores() {
+        return ++m_equal_scores;
+    }
+
 #if _CACHE_TOP_SCORE_
-    inline void adapt_top_sum(double add, double sub) {
+    inline void adapt_top_sum(expr * e, double add, double sub) {
+#if _PAWS_
+        m_top_sum += m_weights.find(e) * (add - sub);
+#else
         m_top_sum += add - sub;
+#endif
     }
 
     inline void set_top_sum(double new_score) {
@@ -278,19 +318,21 @@ public:
     }
 #endif
 
-    void uct_forget(ptr_vector<expr> & as) {
+#if _UCT_
+    void uct_forget(goal_ref const & g) {
         expr * e;
         unsigned touched_old, touched_new;
 
-        for (unsigned i = 0; i < as.size(); i++)
+        for (unsigned i = 0; i < g->size(); i++)
         {
-            e = as[i];
+            e = g->form(i);
             touched_old = m_scores.find(e).touched;
             touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
             m_scores.find(e).touched = touched_new;
             m_touched += touched_new - touched_old;
         }
     }
+#endif
 
     void initialize(app * n) {
         // Build score table
@@ -367,12 +409,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(ptr_vector<expr> const & as) {
+    void calculate_expr_distances(goal_ref const & g) {
         // precondition: m_scores is set up.
-        unsigned sz = as.size();
+        unsigned sz = g->size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(as[i]));
+            stack.push_back(to_app(g->form(i)));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -420,12 +462,12 @@ public:
         quick_for_each_expr(ffd_proc, visited, e);
     }
 
-    void initialize(ptr_vector<expr> const & as) {
+    void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = as.size();
+        unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = as[i];
+            expr * e = g->form(i);
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
             else
@@ -440,7 +482,7 @@ public:
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = as[i];
+            expr * e = g->form(i);
             // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
             initialize_recursive(e);
@@ -452,7 +494,7 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(as);
+        calculate_expr_distances(g);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
@@ -465,16 +507,49 @@ public:
         //}
 #endif
 
+#if _PAWS_
+        for (unsigned i = 0; i < sz; i++)
+        {
+            expr * e = g->form(i);
+        	if (!m_weights.contains(e))
+        		m_weights.insert(e, _PAWS_INIT_);
+        }
+#endif
+
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-            setup_occs(as[i]);
+            setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-        m_touched = _UCT_INIT_ ? as.size() : 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
 #endif
     }
 
+#if _PAWS_
+    void increase_weight(expr * e)
+    {
+        //printf("Increasing %d to", m_weights.find(e));
+        m_weights.find(e)++;
+        //m_weights.find(e) *= 1.1;
+        //printf(" %d\n", m_weights.find(e));
+    }
+
+    void decrease_weight(expr * e)
+    {
+        unsigned old_weight = m_weights.find(e);
+        m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_;
+        //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1;
+        //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e));
+    }
+
+    unsigned get_weight(expr * e)
+    //double get_weight(expr * e)
+    {
+        return m_weights.find(e);
+    }
+#endif
+
 #if _REAL_RS_ || _REAL_PBFS_
     void make_assertion(expr * e)
     {
@@ -608,7 +683,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(ptr_vector<expr> const & as) {
+    void randomize(goal_ref const & g) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -622,13 +697,13 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? as.size() : 1;
-        for (unsigned i = 0; i < as.size(); i++)
-            m_scores.find(as[i]).touched = 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
 #endif
     }              
 
-    void reset(ptr_vector<expr> const & as) {
+    void reset(goal_ref const & g) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -638,9 +713,9 @@ public:
         }
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? as.size() : 1;
-        for (unsigned i = 0; i < as.size(); i++)
-            m_scores.find(as[i]).touched = 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
 #endif
     }              
 
@@ -765,6 +840,7 @@ public:
             const mpz & v1 = get_value(arg1);
             
             if (negated) {                    
+                //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0;
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << std::endl; );
@@ -811,40 +887,209 @@ public:
             SASSERT(a->get_num_args() == 2);
             const mpz & x = get_value(a->get_arg(0));
             const mpz & y = get_value(a->get_arg(1));
-            unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
+            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
 
             if (negated) {
                 if (m_mpz_manager.gt(x, y))
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(x, y, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+/*                  mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_gt = 0;
+                    unsigned curr_gt = 0;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 1;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 0;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
+                    m_mpz_manager.del(x_copy);
+                    m_mpz_manager.del(y_copy);*/
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);                            
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));                            
+                    double dbl = 1.0 - n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    m_mpz_manager.del(diff);
+#endif
+                }
+            }
+            else {
+                if (m_mpz_manager.le(x, y))                        
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(y, x, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-                }
-            }
-            else {
-                if (m_mpz_manager.le(x, y))                        
+                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+/*                  mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_le = 1;
+                    unsigned curr_le = 1;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 0;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 1;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));
-                    double dbl = n.get_double();
+                    double dbl = 1.0 - n.get_double();
                     res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
             }
             TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                     m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
         }
-        else if (m_bv_util.is_bv_sle(n)) { // x <= y
+/*        else if (m_bv_util.is_bv_sle(n)) { // x <= y
+            app * a = to_app(n);
+            SASSERT(a->get_num_args() == 2);
+            const mpz & x = get_value(a->get_arg(0));
+            const mpz & y = get_value(a->get_arg(1));
+            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
+
+            mpz x_unsigned;
+            mpz y_unsigned;
+            const mpz & p = m_powers(bv_sz);
+            const mpz & p_half = m_powers(bv_sz-1);
+            if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } 
+            if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); }                 
+
+            if (negated) {
+                if (x_unsigned > y_unsigned)
+                    res = 1.0; 
+                else {
+                    mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_gt = 0;
+                    unsigned curr_gt = 0;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 1;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 0;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
+                    m_mpz_manager.del(x_copy);
+                    m_mpz_manager.del(y_copy);
+                }
+            }
+            else {
+                if (x_unsigned <= y_unsigned)                        
+                    res = 1.0; 
+                else {
+                    mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_le = 1;
+                    unsigned curr_le = 1;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 0;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 1;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);
+                }
+            }
+            TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
+                                    m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
+
+            m_mpz_manager.del(x_unsigned);
+            m_mpz_manager.del(y_unsigned);
+        }*/
+      else if (m_bv_util.is_bv_sle(n)) { // x <= y
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 2);
             mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0)));
@@ -857,31 +1102,61 @@ public:
 
             if (negated) {
                 if (x > y)
-                    res = 1.0;
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(x, y, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
+                    res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);
                     rational n(diff);
                     n /= p;
-                    double dbl = n.get_double();
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    double dbl = 1.0 - n.get_double();
+                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
             else {
                 if (x <= y)
-                    res = 1.0;
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(y, x, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
+                    res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
+                    SASSERT(!m_mpz_manager.is_neg(diff));
                     rational n(diff);
                     n /= p;
-                    double dbl = n.get_double();
+                    double dbl = 1.0 - n.get_double();
                     res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
@@ -1031,13 +1306,13 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         if (sz == 1)
             return get_constants();
         m_temp_constants.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * q = as[i];
+            expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -1051,22 +1326,22 @@ public:
         return m_temp_constants;
     }
 
-    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
             for (unsigned i = pos; i < sz; i++) {
-                expr * q = as[i];
+                expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             for (unsigned i = 0; i < pos; i++) {
-                expr * q = as[i];
+                expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             return 0;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_walksat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
-            expr * q = get_unsat_assertion(as, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(g, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
             if (!q)
                 return m_temp_constants;
@@ -1143,20 +1418,66 @@ public:
             return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_crsat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
-        expr * q = get_unsat_assertion(as, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(g, sz, pos);
         if (!q)
             return m_temp_constants;
 
         return go_deeper(q);
     }
 
-    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as, unsigned int flip) {
-        unsigned sz = as.size();
+    void go_deeper_only(expr * e) {
+            //if (m_manager.is_bool(e)) {
+                if (m_manager.is_and(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    unsigned cnt_unsat = 0, pos = -1;
+                    for (unsigned int i = 0; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+                        //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q);
+                    }
+                    go_deeper(args[pos]);
+                }
+                else if (m_manager.is_or(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    for (unsigned int i = 0; i < sz; i++) {
+                        expr * q = args[i];
+                        go_deeper(q);
+                    }
+                }
+            //}
+                else
+                {
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+                }
+    }
+
+    ptr_vector<func_decl> & get_unsat_constants_only(expr * e) {
+            if (e && !m_temp_constants.size())
+                go_deeper_only(e);
+
+            return m_temp_constants;
+    }
+
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
 
         if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(as[0]), m_one))
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            {
+                m_temp_constants.reset();
                 return m_temp_constants;
+            }
             else
                 return get_constants();
         }
@@ -1169,11 +1490,12 @@ public:
 #if _PROBABILISTIC_UCT_
             double sum_score = 0.0;
             unsigned start_index = get_random_uint(16) % sz;
-            
+
             for (unsigned i = start_index; i < sz; i++)
             {
                 expr * e = g->form(i);
                 vscore = m_scores.find(e);
+
 #if _PROBABILISTIC_UCT_ == 2
                 double q = vscore.score * vscore.score; 
 #else
@@ -1203,7 +1525,7 @@ public:
 #else
             double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = as[i];
+                expr * e = g->form(i);
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1221,12 +1543,12 @@ public:
                 return m_temp_constants;
 
 #if _UCT_ == 1 || _UCT_ == 3
-            m_scores.find(as[pos]).touched++;
+            m_scores.find(g->form(pos)).touched++;
             m_touched++;
 #elif _UCT_ == 2
-            m_scores.find(as[pos]).touched = flip; 
+            m_scores.find(g->form(pos)).touched = flip; 
 #endif
-            expr * e = as[pos];
+            expr * e = g->form(pos);
 //            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
@@ -1304,12 +1626,15 @@ public:
         }
     }
     
+    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
 
-    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned int flip) {
-        unsigned sz = as.size();
-
-        if (sz == 1)
-            return as[0];
+        if (sz == 1) {
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_zero))
+                return g->form(0);
+            else
+                return 0;
+        }
 
         m_temp_constants.reset();
 #if _FOCUS_ == 1
@@ -1353,12 +1678,12 @@ public:
 #else
         double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = as[i];
+                expr * e = g->form(i);
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #elif _UCT_ == 3
@@ -1371,13 +1696,13 @@ public:
             return 0;
 
 #if _UCT_ == 1 || _UCT_ == 3
-        m_scores.find(as[pos]).touched++;
+        m_scores.find(g->form(pos)).touched++;
         m_touched++;
 #elif _UCT_ == 2
         m_scores.find(g->form(pos)).touched = flip; 
 #endif
 //        return m_list_false[pos];
-        return as[pos];
+        return g->form(pos);
 
 #elif _BFS_ == 3
         unsigned int pos = -1;
@@ -1431,7 +1756,7 @@ public:
         unsigned int pos = get_random_uint(16) % sz;
         return get_unsat_assertion(g, sz, pos);
 #endif
-        return as[pos];
+        return g->form(pos);
 #elif _FOCUS_ == 2
 #if _BFS_
         unsigned int pos = flip % sz;
@@ -1441,6 +1766,23 @@ public:
         return get_unsat_constants_crsat(g, sz, pos);
 #endif
     }
+
+    expr * get_new_unsat_assertion(goal_ref const & g, expr * e) {
+        unsigned sz = g->size();
+
+        if (sz == 1)
+            return 0;
+
+        m_temp_constants.reset();
+
+        unsigned cnt_unsat = 0, pos = -1;
+        for (unsigned i = 0; i < sz; i++)
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i;	
+
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+    }
 };
 
 #endif
\ No newline at end of file
diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp
index ac53ca0c8..a7870176d 100644
--- a/src/tactic/smtlogics/qfbv_tactic.cpp
+++ b/src/tactic/smtlogics/qfbv_tactic.cpp
@@ -28,6 +28,8 @@ Notes:
 #include"bv_size_reduction_tactic.h"
 #include"aig_tactic.h"
 #include"sat_tactic.h"
+//#include"nnf_tactic.h"
+//#include"sls_tactic.h"
 
 #define MEMLIMIT 300
 
@@ -93,6 +95,32 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) {
                             mk_sat_tactic(m));
 #endif    
     
+    /* use full sls
+    tactic * st = using_params(and_then(preamble_st,
+                                        cond(mk_is_qfbv_probe(),
+                                             cond(mk_is_qfbv_eq_probe(),
+                                                  and_then(mk_bv1_blaster_tactic(m),
+                                                           using_params(mk_smt_tactic(), solver_p)),
+                                                  and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))),
+                                             mk_smt_tactic())),
+                               main_p);*/
+
+    /* use pure dpll
+    tactic * st = using_params(and_then(mk_simplify_tactic(m),
+                                        cond(mk_is_qfbv_probe(),
+                                                  and_then(mk_bit_blaster_tactic(m),
+                                                           when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)),
+                                                                and_then(using_params(and_then(mk_simplify_tactic(m),
+                                                                                               mk_solve_eqs_tactic(m)),
+                                                                                      local_ctx_p),
+                                                                         if_no_proofs(cond(mk_produce_unsat_cores_probe(),
+                                                                                           mk_aig_tactic(),
+                                                                                           using_params(mk_aig_tactic(),
+                                                                                                        big_aig_p))))),
+                                                           new_sat),
+                                             mk_smt_tactic())),
+                               main_p);*/
+
     tactic * st = using_params(and_then(preamble_st,
                                         // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function
                                         // symbols. In this case, we should not use 

From 8a30a2caa9f6644866d855a247f621e47cee95e4 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 00:32:45 +0100
Subject: [PATCH 052/108] Almost cleaned up version.

---
 src/tactic/sls/sls_compilation_settings.h |  156 +--
 src/tactic/sls/sls_engine.cpp             | 1168 +++------------------
 src/tactic/sls/sls_engine.h               |   89 +-
 src/tactic/sls/sls_evaluator.h            |  262 +----
 src/tactic/sls/sls_tactic.cpp             |    6 +-
 src/tactic/sls/sls_tracker.h              |  904 ++--------------
 6 files changed, 315 insertions(+), 2270 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index d2b899dd8..9add78daa 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,167 +22,13 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
-// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
-#define _BFS_ 0
-
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
-#define _FOCUS_ 1
-
-// probability of choosing the same assertion again in the next step
-#define _PERC_STICKY_ 0
-
-// do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 0
-
-// shall we use additive weighting scheme?
-#define _PAWS_ 5
-#define _PAWS_INIT_ 40
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 1
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 100
-// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 2.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// should score of discunctions be calculated by multiplication of the inverse score rather than min?
-#define _SCORE_OR_MUL_ 0
-
-// do we use some kind of variable neighbourhood-search?
-// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
-#define _VNS_ 0
-
-// shall we check 2-bit flips in plateaus using Monte Carlo?
-#define _VNS_MC_ 0
-
-// how many 2-bit flips shall we try per bit?
-#define _VNS_MC_TRIES_ 1
-
-// shall we check another assertion if no improving step was found in the first one?
-#define _VNS_REPICK_ 0
-
-// what is the probability of doing so (percentage)?
-#define _VNS_PERC_ 100
-
-// do a decreasing move with percentage ...
-#define _INSIST_PERC_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no
-// 1 = yes, by multiplying it with some factor
-// 2 = yes, by squaring it
-// 3 = yes, by setting it to zero
-// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.5
-
-// shall we toggle the weight after each restart?
-#define _WEIGHT_TOGGLE_ 0
-
-// do we use intensification steps in local minima? if so, how many?
-#define _INTENSIFICATION_ 0
-#define _INTENSIFICATION_TRIES_ 0
-
-// what is the percentage of random moves in plateaus (instead of full randomization)?
-#define _PERC_PLATEAU_MOVES_ 0
-
-// shall we repick assertion when randomizing in a plateau or use the current one?
-// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 20.0
-
-// is uct clause selection probabilistic similar to variable selection in sparrow?
-// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
-#define _PROBABILISTIC_UCT_ 0
-
-// additive constants for probabilistic uct > 0
-#define _UCT_EPS_ 0.0001
-
-// shall we reset _UCT_ touched values after restart?
-#define _UCT_RESET_ 0
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 0
-
-// do we gradually reduce the touched values of _UCT_?
-#define _UCT_FORGET_ 0
-#define _UCT_FORGET_FACTOR_ 0.9
-
 // shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
-// shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 0
-
-// shall we try multiplication by 3?
-#define _USE_MUL3_ 0
-
-// shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 0
-
-// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 0
+#define _USE_ADDSUB_ 0
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
-#define _REAL_PBFS_ 0
-
-// how many bits do we neglect in each iteration?
-#define _SKIP_BITS_ 0
-
-// when randomizing local, what is the probability for changing a single bit?
-// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
-#define _PERC_CHANGE_ 0
-
-// do we use random steps for noise?
-// 0 = no, 1 = randomize local, 2 = make random move
-#define _TYPE_RSTEP_ 0
-
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
 
 // shall we use early pruning for incremental update?
 #define _EARLY_PRUNE_ 1
 
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-
-#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
-InvalidConfiguration;
-#endif
-#if (_PROBABILISTIC_UCT_ && !_UCT_)
-InvalidConfiguration;
-#endif
-#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
-InvalidConfiguration;
-#endif
-#if (_PERC_CHANGE_ == 50)
-InvalidConfiguration;
-#endif
-#if (_PERC_STICKY_ && !_FOCUS_)
-InvalidConfiguration;
-#endif
-
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 342e649af..c240a0c51 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -44,6 +44,7 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) :
     m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers)
 {
     updt_params(p);
+    m_tracker.updt_params(p);
 }
 
 sls_engine::~sls_engine() {
@@ -52,20 +53,21 @@ sls_engine::~sls_engine() {
     m_mpz_manager.del(m_two);
 }
 
-double sls_engine::get_restart_armin(unsigned cnt_restarts)
-{
-    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-    //printf("armin: %f\n", pow(1.1, inner_id + 1));
-    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
-}    
-
 void sls_engine::updt_params(params_ref const & _p) {
     sls_params p(_p);
     m_produce_models = _p.get_bool("model", false);
-    m_max_restarts = p.restarts();
+    m_max_restarts = p.max_restarts();
     m_tracker.set_random_seed(p.random_seed());
-    m_plateau_limit = p.plateau_limit();
+    m_walksat = p.walksat();
+    m_walksat_repick = p.walksat_repick();
+    m_paws_sp = p.paws_sp();
+    m_wp = p.wp();
+    m_vns_mc = p.vns_mc();
+    m_vns_repick = p.vns_repick();
+
+    m_restart_base = p.restart_base();
+    m_restart_next = m_restart_base;
+    m_restart_init = p.restart_init();
 }
 
 void sls_engine::checkpoint() {
@@ -74,15 +76,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
+bool sls_engine::full_eval(model & mdl) {
     bool res = true;
 
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(g->form(i), o, true))
+        if (!mdl.eval(m_assertions[i], o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -93,93 +95,58 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     return res;
 }
 
-double sls_engine::top_score(goal_ref const & g) {
-#if 0
-    double min = m_tracker.get_score(g->form(0));
-    unsigned sz = g->size();
-    for (unsigned i = 1; i < sz; i++) {
-        double q = m_tracker.get_score(g->form(i));
-        if (q < min) min = q;
-    }
-    TRACE("sls_top", tout << "Score distribution:";
-    for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(g->form(i));
-    tout << " MIN: " << min << std::endl;);
-    return min;
-#else
+double sls_engine::top_score() {
     double top_sum = 0.0;
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = g->form(i);
+        expr * e = m_assertions[i];
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(g->form(i));
+        tout << " " << m_tracker.get_score(m_assertions[i]);
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
-#if _CACHE_TOP_SCORE_
     m_tracker.set_top_sum(top_sum);
-#endif
 
     return top_sum / (double)sz;
-#endif
 }
 
-double sls_engine::rescore(goal_ref const & g) {
+double sls_engine::rescore() {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score(g);
+    return top_score();
 }
 
-double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
-#else
-    return top_score(g);
-#endif
+    return (m_tracker.get_top_sum() / m_assertions.size());
 }
 
-double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
-#else
-    return top_score(g);
-#endif
+    return (m_tracker.get_top_sum() / m_assertions.size());
 }
 
-double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-#if _EARLY_PRUNE_
+double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
-        return (m_tracker.get_top_sum() / g->size());
-#else
-        return top_score(g);
-#endif
-    else
-        return 0.0;
-#else
-    NOT_IMPLEMENTED_YET();
-#endif
-}
-
-double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-    m_stats.m_incr_evals++;
-    if (m_evaluator.update_prune_new(fd, new_value))
-        return (m_tracker.get_top_sum() / g->size());
+        return (m_tracker.get_top_sum() / m_assertions.size());
     else
         return 0.0;
 }
 
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if(
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
@@ -187,9 +154,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 #endif
 
 #if _EARLY_PRUNE_
-    double r = incremental_score_prune(g, fd, temp);
+    double r = incremental_score_prune(fd, temp);
 #else
-    double r = incremental_score(g, fd, temp);
+    double r = incremental_score(fd, temp);
 #endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
@@ -198,7 +165,7 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
     m_mpz_manager.del(old_value);
 #endif
 
-    //if (r >= best_score) {
+    // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
         m_tracker.reset_equal_scores();
         best_score = r;
@@ -206,45 +173,6 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
         m_mpz_manager.set(best_value, temp);
         return true;
     }
-    /*else if (r == best_score) {
-        if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0)
-        {
-            best_score = r;
-            best_const = fd_inx;
-            m_mpz_manager.set(best_value, temp);
-            return true;
-        }
-    }*/
-
-    return false;
-}
-
-bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                double & best_score, unsigned & best_const, mpz & best_value) {
-
-    double r = incremental_score_prune_new(g, fd, temp);
-
-    if (r >= best_score) {
-        best_score = r;
-        best_const = fd_inx;
-        m_mpz_manager.set(best_value, temp);
-        return true;
-    }
-
-    return false;
-}
-
-// same as what_if, but only applied to the score of a specific atom, not the total score
-bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                    double & best_score, unsigned & best_const, mpz & best_value) {
-    m_evaluator.update(fd, temp);
-    double r = m_tracker.get_score(e);
-    if (r >= best_score) {
-        best_score = r;
-        best_const = fd_inx;
-        m_mpz_manager.set(best_value, temp);
-        return true;
-    }
 
     return false;
 }
@@ -261,22 +189,6 @@ void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value,
 
 }
 
-// Andreas: do we really need all those temporary mpzs?
-void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-    mpz temp, mask, mask2;
-    m_mpz_manager.mul(old_value, m_two, temp);
-    m_mpz_manager.set(mask, m_powers(bv_sz));
-    m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-    m_mpz_manager.bitwise_and(temp, mask2, result);
-    m_mpz_manager.del(temp);
-    m_mpz_manager.del(mask);
-    m_mpz_manager.del(mask2);
-}
-
-void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-    m_mpz_manager.div(old_value, m_two, result);
-}
-
 void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
     unsigned shift;
     m_mpz_manager.add(old_value, m_one, incremented);
@@ -334,7 +246,7 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         // inversion doesn't make sense, let's do a flip instead.
         if (mt == MV_INV) mt = MV_FLIP;
 #else
-        mt = MV_FLIP;
+        move_type mt = MV_FLIP;
 #endif
         unsigned bit = 0;
 
@@ -373,216 +285,40 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout););
     }
 
-    m_evaluator.update(fd, new_value);
+    m_evaluator.serious_update(fd, new_value);
     m_mpz_manager.del(new_value);
 }
 
-void sls_engine::mk_random_move(goal_ref const & g) {
-    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
-}
-
-// will use VNS to ignore some possible moves and increase the flips per second
-double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-    mpz old_value, temp;
-    unsigned bv_sz, max_bv_sz = 0;
-    double new_score = score;
-
-    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
-        func_decl * fd = to_evaluate[i];
-        sort * srt = fd->get_range();
-        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-            if (!m_mpz_manager.is_even(old_value)) {
-                // for odd values, try +1
-                mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_INC;
-            }
-            else {
-                // for even values, try -1
-                mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_DEC;
-            }
-
-            // try inverting
-            mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_INV;
-
-            // try to flip lsb
-            mk_flip(srt, old_value, 0, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                new_bit = 0;
-                move = MV_FLIP;
-            }
-        }
-
-        // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
-        SASSERT(check == score);
-    }
-
-    // we can either check the condition once in the beginning or check it repeatedly after every bit
-#if _VNS_ == 1
-    for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
-#else
-    if (new_score <= score)
-        for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
-#endif
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // What would happen if we flipped bit #j ?                
-                if (j < bv_sz)
-                {
-                    mk_flip(srt, old_value, j, temp);
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-    return new_score;
-}
-
-double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-    mpz old_value, temp;
-    unsigned bv_sz, max_bv_sz = 0;
-    double new_score = score;
-
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
-        func_decl * fd = to_evaluate[i];
-        sort * srt = fd->get_range();
-        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-            // try inverting
-            mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_INV;
-
-            if (!m_mpz_manager.is_even(old_value)) {
-                // for odd values, try +1
-                mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_INC;
-            }
-            else {
-                // for even values, try -1
-                mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_DEC;
-            }
-
-            // try to flip lsb
-            mk_flip(srt, old_value, 0, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                new_bit = 0;
-                move = MV_FLIP;
-            }
-        }
-
-        // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
-        SASSERT(check == score);
-    }
-
-    for (unsigned j = 1; j < max_bv_sz; j++)
-    {
-        for (unsigned i = 0; i < to_evaluate.size(); i++) {
-            func_decl * fd = to_evaluate[i];
-            sort * srt = fd->get_range();
-            bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-            // What would happen if we flipped bit #j ?                
-            if (j < bv_sz)
-            {
-                mk_flip(srt, old_value, j, temp);
-
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                    new_bit = j;
-                    move = MV_FLIP;
-                }
-            }
-            // reset to what it was before
-            double check = incremental_score(g, fd, old_value);
-            SASSERT(check == score);
-        }
-    }
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-    return new_score;
-}
-
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-    mpz temp2;
-#endif
     unsigned bv_sz;
-#if _INSIST_PERC_
-    double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score;
-#else
     double new_score = score;
-#endif
 
     m_tracker.reset_equal_scores();
 
-//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
     for (unsigned i = 0; i < to_evaluate.size(); i++) {
-//    for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) {
-//    for (unsigned i = to_evaluate.size(); i-- > 0; ) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
         m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
         // first try to flip every bit
-#if _SKIP_BITS_
-        for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
-#else
-//        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
         for (unsigned j = 0; j < bv_sz; j++) {
-//        for (unsigned j = bv_sz; j-- > 0; ) {
-#endif
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            //if (m_tracker.get_random_uint(1))
-            //if ((move != MV_FLIP) || (new_bit > j))
-            //{
-            //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) {
-            //    new_bit = j;
-            //    move = MV_FLIP;
-            //}
-            //}
-            //else
-            //{
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
-            //}
         }
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -590,76 +326,41 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                //if (m_tracker.get_random_uint(1))
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                //if (m_tracker.get_random_uint(1))
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            //if (m_tracker.get_random_uint(1))
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
-
-#if _USE_UNARY_MINUS_
-            mk_inc(bv_sz, temp, temp2);
-            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                move = MV_UMIN;
-#endif
-
-#if _USE_MUL2DIV2_
-            // try multiplication by 2
-            mk_mul2(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_MUL2;
-
-#if _USE_MUL3_
-            // try multiplication by 3
-            mk_add(bv_sz, old_value, temp, temp2);
-            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                move = MV_MUL3;
-#endif
-
-            // try division by 2
-            mk_div2(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_DIV2;
-#endif
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         // Andreas: does not hold anymore now that we use top level score caching
         //SASSERT(check == score);
     }
 
     m_mpz_manager.del(old_value);
     m_mpz_manager.del(temp);
-#if _USE_MUL3_
-    m_mpz_manager.del(temp2);
-#endif
-
-    if ((new_score == score) && 1)// (m_tracker.get_random_uint(1)))
-        best_const = -1;
 
     return new_score;
 }
 
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double score,
                         unsigned & best_const, mpz & best_value) {
     mpz old_value, temp, temp2;
     unsigned bv_sz;
     double new_score = score;
 
-//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
     for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
@@ -667,22 +368,21 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> &
         m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) {
-//            for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
             for (unsigned j = 0; j < bv_sz; j++) {
                 mk_flip(srt, old_value, j, temp);
-                for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++)
+                for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++)
                 {
                     unsigned k = m_tracker.get_random_uint(16) % bv_sz;
                     while (k == j)
                         k = m_tracker.get_random_uint(16) % bv_sz;
                     mk_flip(srt, temp, k, temp2);
-                    what_if(g, fd, i, temp2, new_score, best_const, best_value);
+                    what_if(fd, i, temp2, new_score, best_const, best_value);
                 }
             }
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -692,618 +392,89 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> &
     return new_score;
 }
 
-// same as find_best_move but only considers the score of the current expression instead of the overall score
-double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-    mpz old_value, temp;
-    unsigned bv_sz;
-    double new_score = m_tracker.get_score(e);
-    // Andreas: tie breaking not implemented yet
-    // double tie_score = top_score(g);
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
-        func_decl * fd = to_evaluate[i];
-        sort * srt = fd->get_range();
-        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-        // first try to flip every bit
-        for (unsigned j = 0; j < bv_sz; j++) {
-            // What would happen if we flipped bit #i ?                
-            mk_flip(srt, old_value, j, temp);
-
-            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
-                new_bit = j;
-                move = MV_FLIP;
-            }
-        }
-
-        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-            if (!m_mpz_manager.is_even(old_value)) {
-                // for odd values, try +1
-                mk_inc(bv_sz, old_value, temp);
-                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_INC;
-            }
-            else {
-                // for even values, try -1
-                mk_dec(bv_sz, old_value, temp);
-                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_DEC;
-            }
-
-            // try inverting
-            mk_inv(bv_sz, old_value, temp);
-            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                move = MV_INV;
-        }
-
-        // reset to what it was before
-        m_evaluator.update(fd, old_value);
-    }
-
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-    return new_score;
-}
-
-// first try of intensification ... does not seem to be efficient
-bool sls_engine::handle_plateau(goal_ref const & g)
-{
-    unsigned sz = g->size();
-#if _BFS_
-    unsigned pos = m_stats.m_moves % sz;
-#else
-    unsigned pos = m_tracker.get_random_uint(16) % sz;
-#endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-    if (!e)
-        return 0;
-
-    expr * q = m_tracker.get_unsat_expression(e);
-    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-    for (unsigned i = 0; i < to_evaluate.size(); i++)
-    {
-        m_tracker.get_value(to_evaluate[i]);
-        m_old_values.push_back(&m_tracker.get_value(to_evaluate[i]));
-    }
-    unsigned new_const = (unsigned)-1, new_bit = 0;
-    mpz new_value;
-    move_type move;
-    for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-    {
-        // Andreas: Could be extended to use (best) score but this is computationally more expensive.
-        find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
-
-        if (new_const == static_cast<unsigned>(-1)) {
-            // Andreas: Actually this should never happen.
-            NOT_IMPLEMENTED_YET();
-        }
-        else {
-            m_stats.m_moves++;
-            func_decl * fd = to_evaluate[new_const];
-
-            switch (move) {
-            case MV_FLIP: m_stats.m_flips++; break;
-            case MV_INC: m_stats.m_incs++; break;
-            case MV_DEC: m_stats.m_decs++; break;
-            case MV_INV: m_stats.m_invs++; break;
-            case MV_UMIN: m_stats.m_umins++; break;
-            case MV_MUL2: m_stats.m_mul2s++; break;
-            case MV_MUL3: m_stats.m_mul3s++; break;
-            case MV_DIV2: m_stats.m_div2s++; break;
-            }
-
-            m_evaluator.update(fd, new_value);
-        }
-
-        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-            return 1;
-    }
-
-    for (unsigned i = 0; i < to_evaluate.size(); i++)
-        m_tracker.set_value(to_evaluate[i], *m_old_values[i]);
-
-    m_old_values.reset();
-
-    return 0;
-}
-
-// what_if version needed in the context of 2nd intensification try, combining local and global score
-bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                double & best_score, mpz & best_value, unsigned i) {
-
-    double global_score = incremental_score(g, fd, temp);
-    double local_score = m_tracker.get_score(e);
-    double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
-
-    if (new_score >= best_score) {
-        best_score = new_score;
-        m_mpz_manager.set(best_value, temp);
-        return true;
-    }
-
-    return false;
-}
-
-// find_best_move version needed in the context of 2nd intensification try
-double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-{
-    mpz old_value, temp;
-    double best_score = 0;
-
-    sort * srt = fd->get_range();
-    unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-    m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-    for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
-        mk_flip(srt, old_value, j, temp);
-        what_if(g, e, fd, temp, best_score, best_value, i);
-    }
-
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-
-    return best_score;
-}
-
-// second try to use intensification ... also not very effective
-bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
-{
-    unsigned sz = g->size();
-#if _BFS_
-    unsigned new_const = m_stats.m_moves % sz;
-#else
-    unsigned new_const = m_tracker.get_random_uint(16) % sz;
-#endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-    if (!e)
-        return 0;
-
-    expr * q = m_tracker.get_unsat_expression(e);
-    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-
-    new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-    func_decl * fd = to_evaluate[new_const];
-
-    mpz new_value;
-    //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-    unsigned new_bit = 0;
-    double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-
-    for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-    {
-        new_score = find_best_move_local(g, q, fd, new_value, i);
-
-        m_stats.m_moves++;
-        m_stats.m_flips++;
-
-        global_score = incremental_score(g, fd, new_value);
-        local_score = m_tracker.get_score(q);
-
-        SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
-
-        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-            return 1;
-    }
-
-    return 0;
-}
-
 // main search loop
-lbool sls_engine::search(goal_ref const & g) {
+lbool sls_engine::search() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
-    unsigned new_const = (unsigned)-1, new_bit = 0;
+    unsigned new_const = (unsigned)-1, new_bit;
     mpz new_value;
     move_type move;
-    unsigned plateau_cnt = 0;
 
-    score = rescore(g);
-    unsigned sz = g->size();
-
-    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-    tout << "Score distribution:";
-    for (unsigned i = 0; i < g->size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-    tout << " TOP: " << score << std::endl;);
-
-#if _PERC_STICKY_
-    expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
-#endif
-
-#if _RESTARTS_ == 1
-    while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#elif _RESTARTS_ == 2
-    while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#elif _RESTARTS_ == 3
-    while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#else
-    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#endif
-        //if (m_stats.m_stopwatch.get_current_seconds() > 10.0)
-        //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);}
+    score = rescore();
+    unsigned sz = m_assertions.size();
 
+    while (check_restart(m_stats.m_moves)) {
         checkpoint();
         m_stats.m_moves++;
+        if (m_stats.m_moves % m_restart_base == 0)
+            m_tracker.ucb_forget(m_assertions);
 
-#if _UCT_FORGET_
-        //if (m_stats.m_moves % sz == 0)
-        if (m_stats.m_moves % _UCT_FORGET_ == 0)
-            m_tracker.uct_forget(g);
-#endif
-
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
-
-#if _FOCUS_
-#if _PERC_STICKY_
-        if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
-            e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
-#else
-        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
-#endif
-        if (!e)
-        {
-            res = l_true;
-            goto bailout;
-        }
-        //ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_only(e);
-        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+        
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
         {
             res = l_true;
             goto bailout;
         }
-#endif
 
-#if _TYPE_RSTEP_
-        if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+        if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
-#if _TYPE_RSTEP_ == 1
-            m_evaluator.randomize_local(to_evaluate);
-#elif _TYPE_RSTEP_ == 2
             mk_random_move(to_evaluate);
-#endif
-#if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / g->size();
-#else
-            score = top_score(g);
-#endif
+            score = m_tracker.get_top_sum() / sz;
+            continue;
         }
-        continue;
-#endif
 
-#if _WEIGHT_DIST_ == 4
-        m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif       
         old_score = score;
         new_const = (unsigned)-1;
-        move = MV_FLIP;
-        new_bit = 0;
 
-#if _VNS_
-        score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
+        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 
-#if _VNS_MC_ > _VNS_REPICK_
-#if _VNS_MC_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
-                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-#endif
-#if _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                {
-                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
-                }
+        if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
+            score = find_best_move_mc(to_evaluate, score, new_const, new_value);
+   
+        /*if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
+        {
+            expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e);
+            if (q)
+            {
+                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move);
             }
-#endif
-#endif
-
-#if _VNS_MC_ < _VNS_REPICK_
-#if _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                {
-                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
-                }
-            }
-#endif
-#if _VNS_MC_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
-                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-#endif
-#endif
-
-#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1)) {
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
-                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-            else {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                {
-                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
-                }
-            }
-        }        
-#endif
-
+        }*/
 
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
-            plateau_cnt++;
-#if _INTENSIFICATION_
-            handle_plateau(g, score);
-            //handle_plateau(g);
-            //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-            //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-#if _PERC_PLATEAU_MOVES_
-            if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
-                mk_random_move(to_evaluate);
+            if (m_walksat && m_walksat_repick)
+                m_evaluator.randomize_local(m_assertions);
             else
-#endif
-#if _REPICK_ == 1
-                m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _REPICK_ == 2
-            {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                    m_evaluator.randomize_local(q);
-                else
-                    m_evaluator.randomize_local(e);
-            }
-#else
-                m_evaluator.randomize_local_n(g, to_evaluate);
-                //m_evaluator.randomize_local(to_evaluate);
-#endif
-#endif
+                m_evaluator.randomize_local(to_evaluate);
 
-#if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / g->size();
-#else
-            score = top_score(g);
-#endif
+            score = m_tracker.get_top_sum() / m_assertions.size();
 
-#if _PAWS_
-            for (unsigned i = 0; i < sz; i++)
+            if (m_paws_sp < 1024)
             {
-                expr * q = g->form(i);
-                if (m_tracker.get_random_uint(16) % 100 < _PAWS_)
+                for (unsigned i = 0; i < sz; i++)
                 {
-                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
-                        m_tracker.decrease_weight(q);
-                }
-                else
-                {
-                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
-                        m_tracker.increase_weight(q);
+                    expr * q = m_assertions[i];
+                    if (m_tracker.get_random_uint(10) < m_paws_sp)
+                    {
+                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
+                            m_tracker.decrease_weight(q);
+                    }
+                    else
+                    {
+                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
+                            m_tracker.increase_weight(q);
+                    }
                 }
             }
-#endif
-
         }
         else {
             func_decl * fd = to_evaluate[new_const];
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
-            score = serious_score(g, fd, new_value);
-#else
-            score = incremental_score(g, fd, new_value);
-#endif
-        }
-    }
-
-bailout:
-    m_mpz_manager.del(new_value);
-
-    return res;
-}
-
-// main search loop
-lbool sls_engine::search_old(goal_ref const & g) {
-    lbool res = l_undef;
-    double score = 0.0, old_score = 0.0;
-    unsigned new_const = (unsigned)-1, new_bit = 0;
-    mpz new_value;
-    move_type move;
-
-    score = rescore(g);
-    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-    tout << "Score distribution:";
-    for (unsigned i = 0; i < g->size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-    tout << " TOP: " << score << std::endl;);
-
-    unsigned plateau_cnt = 0;
-
-    // Andreas: Why do we only allow so few plateaus?
-#if _RESTARTS_
-    while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
-        //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {
-#endif
-        do {
-            checkpoint();
-
-#if _WEIGHT_DIST_ == 4
-            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-
-#if _TYPE_RSTEP_
-            if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-            {
-#if _TYPE_RSTEP_ == 1
-                m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _TYPE_RSTEP_ == 2
-                mk_random_move(g);
-#endif
-                score = top_score(g);
-
-                if (score >= 1.0) {
-                    bool all_true = true;
-                    for (unsigned i = 0; i < g->size() && all_true; i++)
-                        if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                            all_true = false;
-                    if (all_true) {
-                        res = l_true; // sat
-                        goto bailout;
-                    }
-                    else
-                        TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                }
-            }
-#endif
-            old_score = score;
-            new_const = (unsigned)-1;
-
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-            if (!to_evaluate.size())
-            {
-                res = l_true;
-                goto bailout;
-            }
-            TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-                tout << to_evaluate[i]->get_name() << std::endl;);
-
-#if _VNS_
-            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-            if (new_const == static_cast<unsigned>(-1)) {
-                TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++) {
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
-                });
-
-                TRACE("sls_max", m_tracker.show_model(tout);
-                tout << "Scores: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
-                    m_tracker.get_score(g->form(i)) << std::endl;);
-                // Andreas: If new_const == -1, shouldn't score = old_score anyway?
-                score = old_score;
-            }
-            else {
-                // Andreas: Why does randomizing not count as a move? (Now it does.)
-                m_stats.m_moves++;
-                func_decl * fd = to_evaluate[new_const];
-
-                TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
-                switch (move) {
-                case MV_FLIP:
-                    tout << "Flip";
-                    if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
-                    break;
-                case MV_INC:
-                    tout << "+1";
-                    break;
-                case MV_DEC:
-                    tout << "-1";
-                    break;
-                case MV_INV:
-                    tout << "NEG";
-                    break;
-                };
-                tout << ") ; new score = " << std::setprecision(32) << score << std::endl;);
-
-                switch (move) {
-                case MV_FLIP: m_stats.m_flips++; break;
-                case MV_INC: m_stats.m_incs++; break;
-                case MV_DEC: m_stats.m_decs++; break;
-                case MV_INV: m_stats.m_invs++; break;
-                case MV_UMIN: m_stats.m_umins++; break;
-                case MV_MUL2: m_stats.m_mul2s++; break;
-                case MV_MUL3: m_stats.m_mul3s++; break;
-                case MV_DIV2: m_stats.m_div2s++; break;
-                }
-
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
-                score = serious_score(g, fd, new_value);
-#else
-                score = incremental_score(g, fd, new_value);
-#endif
-
-                TRACE("sls", tout << "Score distribution:";
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                tout << " TOP: " << score << std::endl;);
-            }
-
-            if (score >= 0.99999) {
-                //                    if (score >= 1.0) {
-                // score could theoretically be imprecise.
-                // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
-                bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        all_true = false;
-                if (all_true) {
-                    res = l_true; // sat
-                    goto bailout;
-                }
-                else
-                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-            }
-            /*
-            if (m_stats.m_moves % 100 == 0)
-            {
-            verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-            verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-            }*/
-        } while (score > old_score && res == l_undef);
-
-        // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
-        if (score != old_score) {
-            report_tactic_progress("This should not happen I guess.", plateau_cnt);
-            plateau_cnt = 0;
-        }
-        else {
-            m_stats.m_moves++;
-            plateau_cnt++;
-            //report_tactic_progress("Plateau.", plateau_cnt);
-            // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
-            //if (plateau_cnt < m_plateau_limit) {
-            TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
-#if _INTENSIFICATION_
-            handle_plateau(g, score);
-            //handle_plateau(g);
-#else
-            m_evaluator.randomize_local(g, m_stats.m_moves);
-#endif
-            //mk_random_move(g);
-            score = top_score(g);
-
-            if (score >= 1.0) {
-                bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        all_true = false;
-                if (all_true) {
-                    res = l_true; // sat
-                    goto bailout;
-                }
-                else
-                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-            }
+            score = serious_score(fd, new_value);
         }
     }
 
@@ -1321,80 +492,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
-    verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-    verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-    verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
-    verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-    verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-    verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-    verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-    verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-    verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-    verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-    verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl;
-    verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl;
-    verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-    verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl;
-    verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl;
-    verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl;
-    verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl;
-    verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl;
-    verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-    verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-    verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-    verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-    verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
-    verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-    verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-    verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-    verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
-    verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-    verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
-    verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
-    verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-    verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+    for (unsigned i = 0; i < g->size(); i++)
+        assert_expr(g->form(i));    
+
     verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-    verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-    verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-    verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-    verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-    verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-    verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-    verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-    verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-    verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-#if _WEIGHT_DIST_ == 4
-    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-    m_tracker.initialize(g);
-    lbool res = l_undef;
-
-    m_restart_limit = _RESTART_LIMIT_;
-
-    do {
-        checkpoint();
-
-        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search(g);
-
-        if (res == l_undef)
-        {
-#if _RESTART_INIT_
-            m_tracker.randomize(g);
-#else
-            m_tracker.reset(g);
-#endif
-        }
-    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-
-    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+    lbool res = operator()();
 
     if (res == l_true) {
         report_tactic_progress("Number of flips:", m_stats.m_moves);
@@ -1416,33 +521,66 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         mc = 0;
 }
 
-unsigned sls_engine::check_restart(unsigned curr_value)
+lbool sls_engine::operator()() {
+    m_tracker.initialize(m_assertions);
+    lbool res = l_undef;
+
+    do {
+        checkpoint();
+
+        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+        res = search();
+
+        if (res == l_undef)
+        {
+            if (m_restart_init)
+                m_tracker.randomize(m_assertions);
+            else
+                m_tracker.reset(m_assertions);
+        }
+    } while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
+
+    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+    
+    return res;
+}
+
+/* Andreas: Needed for Armin's restart scheme if we don't want to use loops.
+inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
 {
-    if (curr_value > m_restart_limit)
+    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
+}    
+*/
+
+inline unsigned sls_engine::check_restart(unsigned curr_value)
+{
+    if (curr_value > m_restart_next)
     {
+        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter.
+        I leave the other versions as comments in case you want to try it again somewhen.
 #if _RESTART_SCHEME_ == 5
-        m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+        m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
 #elif _RESTART_SCHEME_ == 4
-        m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+        m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
-        m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+        m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base;
 #elif _RESTART_SCHEME_ == 2
-        m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+        m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base;
 #elif _RESTART_SCHEME_ == 1
         if (m_stats.m_restarts & 1)
-        //if (m_stats.m_restarts % 3 == 2)
-            m_restart_limit += _RESTART_LIMIT_;
+            m_restart_next += m_restart_base;
         else
-            m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
-            //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_;
+            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
 #else
-        m_restart_limit += _RESTART_LIMIT_;
-#endif
-#if _WEIGHT_TOGGLE_
-        printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-        m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-#endif
+        m_restart_limit += m_restart_base;
+#endif  */
+        if (m_stats.m_restarts & 1)
+            m_restart_next += m_restart_base;
+        else
+            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
         return 0;
     }
     return 1;
-}
\ No newline at end of file
+}
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 902c6b7a0..ff0e55f24 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,6 +22,7 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
+#include"goal.h"
 
 #include"sls_compilation_settings.h"
 #include"sls_tracker.h"
@@ -35,17 +36,13 @@ public:
         stopwatch       m_stopwatch;
         unsigned        m_full_evals;
         unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs;
 
         stats() :
             m_restarts(0),
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
-            m_umins(0),
-            m_mul2s(0),
-            m_mul3s(0),
-            m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -71,14 +68,22 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
+    ptr_vector<expr> m_assertions;
 
-    unsigned		m_restart_limit;
     unsigned        m_max_restarts;
-    unsigned        m_plateau_limit;
+    unsigned        m_walksat;
+    unsigned        m_walksat_repick;
+    unsigned        m_wp;
+    unsigned        m_vns_mc;
+    unsigned        m_vns_repick;
+    unsigned        m_paws_sp;
+    unsigned        m_restart_base;
+    unsigned        m_restart_next;
+    unsigned        m_restart_init;
 
     ptr_vector<mpz> m_old_values;
 
-    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;
+    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
 public:    
     sls_engine(ast_manager & m, params_ref const & p);
@@ -92,78 +97,46 @@ public:
 
     void updt_params(params_ref const & _p);
 
+    void assert_expr(expr * e) { m_assertions.push_back(e); }
+
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(goal_ref const & g, model & mdl);
-    
+    bool full_eval(model & mdl);
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
-    void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
-    void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result);
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
-    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-
-    double find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-
-    double find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value);
-
-    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    
-    
-    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                 double & best_score, mpz & best_value, unsigned i);
-    
-    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
-    
-
-    lbool search(goal_ref const & g);    
+    lbool search(void);    
 
+    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
-    lbool search_old(goal_ref const & g);
-    double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
 
-    bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                 double & best_score, unsigned & best_const, mpz & best_value);
-    double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double top_score();
+    double rescore();
+    double serious_score(func_decl * fd, const mpz & new_value);
+    double incremental_score(func_decl * fd, const mpz & new_value);
 
-    bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                       double & best_score, unsigned & best_const, mpz & best_value);
+    double incremental_score_prune(func_decl * fd, const mpz & new_value);
+    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
 
-    double top_score(goal_ref const & g);
-    double rescore(goal_ref const & g);
-    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
-    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
-
-#if _EARLY_PRUNE_
-    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
-#endif
-
-    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    double find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value);
 
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
-    void mk_random_move(goal_ref const & g);
-
-    bool handle_plateau(goal_ref const & g);
-    bool handle_plateau(goal_ref const & g, double old_score);
 
+    //inline double get_restart_armin(unsigned cnt_restarts);    
     inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 78f2cb79a..37bfa5a2d 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -81,11 +81,7 @@ public:
             case OP_AND: {
                 m_mpz_manager.set(result, m_one);
                 for (unsigned i = 0; i < n_args; i++)
-#if _DIRTY_UP_
-                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i]))  {
-#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result))  {
-#endif
                         m_mpz_manager.set(result, m_zero);
                         break;
                     }
@@ -93,11 +89,7 @@ public:
             }
             case OP_OR: {
                 for (unsigned i = 0; i < n_args; i++)
-#if _DIRTY_UP_
-                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i]))  {
-#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) {
-#endif
                         m_mpz_manager.set(result, m_one);
                         break;
                     }
@@ -105,16 +97,9 @@ public:
             }
             case OP_NOT: {
                 SASSERT(n_args == 1);
-#if _DIRTY_UP_
-                if (m_tracker.is_top_expr(args[0]))
-                    m_mpz_manager.set(result, m_zero);
-                else
-                    m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero);
-#else
                 const mpz & child = m_tracker.get_value(args[0]);
                 SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child));                
                 m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);
-#endif
                 break;
             }
             case OP_EQ: {
@@ -545,9 +530,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
         double new_score;
-#endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
@@ -559,8 +542,7 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 
-#if _REAL_RS_ || _REAL_PBFS_
-                //if (!m_tracker.has_uplinks(cur))
+#if _REAL_RS_
                 if (m_tracker.is_top_expr(cur))
                 {
                     if (m_mpz_manager.eq(new_value,m_one))
@@ -570,25 +552,12 @@ public:
                 }
 #endif
 
+                new_score = m_tracker.score(cur);
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #if _EARLY_PRUNE_
-                new_score = m_tracker.score(cur);
-#if _CACHE_TOP_SCORE_
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
-                m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
-#else
-#if _CACHE_TOP_SCORE_
-                new_score = m_tracker.score(cur);
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                m_tracker.set_score(cur, new_score);
-#else
-                m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
 #endif            
 
                 if (m_tracker.has_uplinks(cur)) {
@@ -617,9 +586,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
         double new_score;
-#endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
@@ -630,25 +597,12 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
+                new_score = m_tracker.score(cur);
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #if _EARLY_PRUNE_
-                new_score = m_tracker.score(cur);
-#if _CACHE_TOP_SCORE_
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
-                m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
-#else
-#if _CACHE_TOP_SCORE_
-                new_score = m_tracker.score(cur);
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                m_tracker.set_score(cur, new_score);
-#else
-                m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
 #endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -684,11 +638,7 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         run_serious_update(max_depth);
-#else
-        run_update(max_depth);
-#endif
     }
 
     void update(func_decl * fd, const mpz & new_value) {
@@ -713,7 +663,6 @@ public:
         run_serious_update(cur_depth);
     }
 
-#if _EARLY_PRUNE_
     unsigned run_update_bool_prune(unsigned cur_depth) {
         expr_fast_mark1 visited;
 
@@ -727,19 +676,15 @@ public:
             expr * cur = cur_depth_exprs[i];
 
             new_score = m_tracker.score(cur); 
-#if _CACHE_TOP_SCORE_
-            //if (!m_tracker.has_uplinks(cur))
             if (m_tracker.is_top_expr(cur))
                 m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
+
             prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
             if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
-            //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
                 pot_benefits = 1;
             if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
-            //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
                 pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
@@ -754,9 +699,6 @@ public:
                     }
                 }
             }
-            else
-            {
-            }
         }
 
         cur_depth_exprs.reset();
@@ -770,15 +712,11 @@ public:
                 for (unsigned i = 0; i < cur_size; i++) {
                     expr * cur = cur_depth_exprs[i];
 
-#if _CACHE_TOP_SCORE_
                     new_score = m_tracker.score(cur); 
-                    //if (!m_tracker.has_uplinks(cur))
                     if (m_tracker.is_top_expr(cur))
                         m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
-#else
-                    m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
+
                     if (m_tracker.has_uplinks(cur)) {
                         ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                         for (unsigned j = 0; j < ups.size(); j++) {
@@ -859,161 +797,18 @@ public:
         }
         return run_update_bool_prune(cur_depth);
     }
-#endif
-
-    unsigned run_update_bool_prune_new(unsigned cur_depth) {
-        expr_fast_mark1 visited;
-
-        double prune_score, new_score;
-        unsigned pot_benefits = 0;
-        SASSERT(cur_depth < m_traversal_stack_bool.size());
- 
-        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-
-        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
-            expr * cur = cur_depth_exprs[i];
-
-            new_score = m_tracker.score(cur); 
-            //if (!m_tracker.has_uplinks(cur))
-            if (m_tracker.is_top_expr(cur))
-                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-            prune_score = m_tracker.get_score_prune(cur);
-            m_tracker.set_score(cur, new_score);
-
-            if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
-                pot_benefits = 1;
-            if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
-                pot_benefits = 1;
-
-            if (m_tracker.has_uplinks(cur)) {
-                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                for (unsigned j = 0; j < ups.size(); j++) {
-                    expr * next = ups[j];
-                    unsigned next_d = m_tracker.get_distance(next);
-                    SASSERT(next_d < cur_depth);
-                    if (!visited.is_marked(next)) {
-                        m_traversal_stack_bool[next_d].push_back(next);
-                        visited.mark(next);
-                    }
-                }
-            }
-            else
-            {
-            }
-        }
-
-        cur_depth_exprs.reset();
-        cur_depth--;
- 
-        while (cur_depth != static_cast<unsigned>(-1)) {
-            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-            if (pot_benefits)
-            {
-                unsigned cur_size = cur_depth_exprs.size();
-                for (unsigned i = 0; i < cur_size; i++) {
-                    expr * cur = cur_depth_exprs[i];
-
-                    new_score = m_tracker.score(cur); 
-                    //if (!m_tracker.has_uplinks(cur))
-                    if (m_tracker.is_top_expr(cur))
-                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                    m_tracker.set_score(cur, new_score);
-                    if (m_tracker.has_uplinks(cur)) {
-                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                        for (unsigned j = 0; j < ups.size(); j++) {
-                            expr * next = ups[j];
-                            unsigned next_d = m_tracker.get_distance(next);
-                            SASSERT(next_d < cur_depth);
-                            if (!visited.is_marked(next)) {
-                                m_traversal_stack_bool[next_d].push_back(next);
-                                visited.mark(next);
-                            }
-                        }
-                    }
-                }
-            }
-            cur_depth_exprs.reset();
-            cur_depth--;
-        }
-
-        return pot_benefits;
-    }
-
-    unsigned update_prune_new(func_decl * fd, const mpz & new_value) {
-        m_tracker.set_value(fd, new_value);
-        expr * ep = m_tracker.get_entry_point(fd);
-        unsigned cur_depth = m_tracker.get_distance(ep);
-
-        if (m_traversal_stack_bool.size() <= cur_depth)
-            m_traversal_stack_bool.resize(cur_depth+1);
-        if (m_traversal_stack.size() <= cur_depth) 
-                m_traversal_stack.resize(cur_depth+1);
-
-        if (m_manager.is_bool(ep))
-            m_traversal_stack_bool[cur_depth].push_back(ep);
-        else
-        {
-            m_traversal_stack[cur_depth].push_back(ep);
-            run_update_prune(cur_depth);
-        }
-        return run_update_bool_prune_new(cur_depth);
-    }
 
     void randomize_local(ptr_vector<func_decl> & unsat_constants) {
-        // Randomize _all_ candidates:
-
-        //// bool did_something = false;
-        //for (unsigned i = 0; i < unsat_constants.size(); i++) {
-        //    func_decl * fd = unsat_constants[i];
-        //    mpz temp = m_tracker.get_random(fd->get_range());
-        //    // if (m_mpz_manager.neq(temp, m_tracker.get_value(fd))) {
-        //    //     did_something = true;
-        //    // }
-        //    update(fd, temp);
-        //    m_mpz_manager.del(temp);
-        //}
-
         // Randomize _one_ candidate:
         unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
         func_decl * fd = unsat_constants[r];
-#if _PERC_CHANGE_
-        sort * srt = fd->get_range();
-        mpz temp;
-
-        if (m_manager.is_bool(srt))
-            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-        else
-        {
-            mpz temp2, mask;
-            unsigned bv_sz = m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(temp, m_tracker.get_value(fd));
-
-            for (unsigned bit = 0; bit < bv_sz; bit++)
-                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-                {
-                    m_mpz_manager.set(mask, m_powers(bit));
-                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
-                    m_mpz_manager.set(temp, temp2);
-                }
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(temp2);
-        }
-#else
         mpz temp = m_tracker.get_random(fd->get_range());
-#endif
 
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         serious_update(fd, temp);
-#else
-        update(fd, temp);
-#endif
+
         m_mpz_manager.del(temp);
 
-        TRACE("sls", /*tout << "Randomization candidates: ";
-                        for (unsigned i = 0; i < unsat_constants.size(); i++)
-                            tout << unsat_constants[i]->get_name() << ", ";
-                        tout << std::endl;*/
-                        tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
+        TRACE("sls",    tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
                         tout << "Locally randomized model: " << std::endl; 
                         m_tracker.show_model(tout); );
 
@@ -1023,36 +818,9 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-    void randomize_local(goal_ref const & g, unsigned int flip) {
-        randomize_local(m_tracker.get_unsat_constants(g, flip));
+    void randomize_local(ptr_vector<expr> const & as) {
+        randomize_local(m_tracker.get_unsat_constants(as));
     } 
-
-    void randomize_local_n(goal_ref const & g, ptr_vector<func_decl> & unsat_constants) {
-        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
-        func_decl * fd = unsat_constants[r];
-        sort * srt = fd->get_range();
-        unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); 
-        mpz max_val = m_tracker.get_random(srt);
-        update(fd, max_val);
-        double max_score = m_tracker.get_top_sum() / g->size();
-        mpz temp_val;
-        double temp_score;
-        for (unsigned i = 1; i < 2; i++)
-        //for (unsigned i = 1; i < bv_sz; i++)
-        {
-            m_mpz_manager.set(temp_val, m_tracker.get_random(srt));
-            update(fd, temp_val);
-            temp_score = m_tracker.get_top_sum() / g->size();
-            if (temp_score > max_score)
-            {
-                m_mpz_manager.set(max_val, temp_val);
-                max_score = temp_score;
-            }
-        }
-        update(fd, max_val);
-        m_mpz_manager.del(temp_val);
-        m_mpz_manager.del(max_val);
-    }
 };
 
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 0b6b01e7c..6e1102dd2 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -1507,16 +1507,12 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-                        // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
-                        //mk_ctx_simplify_tactic(m, ctx_p),
-                        // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance!
-                        //mk_simplify_tactic(m),
                         mk_nnf_tactic(m, p));
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
     tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
-//    tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
+    //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 87c90f1f8..65011dc8d 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,7 +20,9 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"goal.h"
+#include"for_each_expr.h"
+#include"ast_smt2_pp.h"
+#include"bv_decl_plugin.h"
 #include"model.h"
 
 #include"sls_compilation_settings.h"
@@ -37,11 +39,7 @@ class sls_tracker {
     mpz                   m_zero, m_one, m_two;
         
     struct value_score { 
-#if _EARLY_PRUNE_
         value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
-#else
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
-#endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
@@ -78,24 +76,22 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
-#if _UCT_
+
+    unsigned              m_walksat;
+    unsigned              m_ucb;
+    double                m_ucb_constant;
+    unsigned              m_ucb_init;
+    double                m_ucb_forget;
     unsigned              m_touched;
-#endif
-#if _REAL_RS_ || _REAL_PBFS_
+    double                m_scale_unsat;
+    unsigned              m_paws_init;
+#if _REAL_RS_
     ptr_vector<expr>	  m_unsat_expr;
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
 #endif
-#if _PAWS_
     obj_map<expr, unsigned> m_weights;
-    //obj_map<expr, double> m_weights;
-#endif
-#if _CACHE_TOP_SCORE_
     double				  m_top_sum;
-#endif
-#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
-    double				  m_weight_dist_factor;
-#endif
     unsigned              m_equal_scores;
 
 public:    
@@ -116,6 +112,17 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+    void updt_params(params_ref const & _p) {
+        sls_params p(_p);
+        m_walksat = p.walksat();
+        m_ucb = p.walksat_ucb();
+        m_ucb_constant = p.walksat_ucb_constant();
+        m_ucb_init = p.walksat_ucb_init();
+        m_ucb_forget = p.walksat_ucb_forget();
+        m_scale_unsat = p.scale_unsat();
+        m_paws_init = p.paws_init();
+    }
+
     unsigned get_formula_size() {
         return m_scores.size();
     }
@@ -141,12 +148,6 @@ public:
         return sum / count;   
     }
 
-#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
-    inline void set_weight_dist_factor(double val) {
-        m_weight_dist_factor = val;
-    }
-#endif
-
     void reset_equal_scores() {
         m_equal_scores = 1;
     }
@@ -155,13 +156,8 @@ public:
         return ++m_equal_scores;
     }
 
-#if _CACHE_TOP_SCORE_
     inline void adapt_top_sum(expr * e, double add, double sub) {
-#if _PAWS_
         m_top_sum += m_weights.find(e) * (add - sub);
-#else
-        m_top_sum += add - sub;
-#endif
     }
 
     inline void set_top_sum(double new_score) {
@@ -171,7 +167,6 @@ public:
     inline double get_top_sum() {
         return m_top_sum;
     }
-#endif
 
     inline void set_value(expr * n, const mpz & r) {
         SASSERT(m_scores.contains(n));
@@ -217,7 +212,6 @@ public:
         return get_score(ep);
     }
 
-#if _EARLY_PRUNE_
     inline void set_score_prune(expr * n, double score) {
         SASSERT(m_scores.contains(n));
         m_scores.find(n).score_prune = score;
@@ -237,7 +231,6 @@ public:
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
     }
-#endif
 
     inline unsigned get_distance(expr * n) {
         SASSERT(m_scores.contains(n));
@@ -271,7 +264,7 @@ public:
         return m_uplinks.find(n);
     }
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
     void debug_real(goal_ref const & g, unsigned flip)
     {
         unsigned count = 0;
@@ -318,21 +311,22 @@ public:
     }
 #endif
 
-#if _UCT_
-    void uct_forget(goal_ref const & g) {
-        expr * e;
-        unsigned touched_old, touched_new;
-
-        for (unsigned i = 0; i < g->size(); i++)
+    inline void ucb_forget(ptr_vector<expr> & as) {
+        if (m_ucb_forget < 1.0)
         {
-            e = g->form(i);
-            touched_old = m_scores.find(e).touched;
-            touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
-            m_scores.find(e).touched = touched_new;
-            m_touched += touched_new - touched_old;
+            expr * e;
+            unsigned touched_old, touched_new;
+
+            for (unsigned i = 0; i < as.size(); i++)
+            {
+                e = as[i];
+                touched_old = m_scores.find(e).touched;
+                touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1);
+                m_scores.find(e).touched = touched_new;
+                m_touched += touched_new - touched_old;
+            }
         }
     }
-#endif
 
     void initialize(app * n) {
         // Build score table
@@ -409,12 +403,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(goal_ref const & g) {
+    void calculate_expr_distances(ptr_vector<expr> const & as) {
         // precondition: m_scores is set up.
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(g->form(i)));
+            stack.push_back(to_app(as[i]));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -462,31 +456,24 @@ public:
         quick_for_each_expr(ffd_proc, visited, e);
     }
 
-    void initialize(goal_ref const & g) {
+    void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
             else
                 printf("this is already in ...\n");
-            // Andreas: Maybe not fully correct.
-#if _FOCUS_ == 2
-            initialize_recursive(proc, visited, e);
-#endif
             for_each_expr(proc, visited, e);
         }
 
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             // Andreas: Maybe not fully correct.
-#if _FOCUS_ == 2 || _INTENSIFICATION_
-            initialize_recursive(e);
-#endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -494,11 +481,11 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(g);
+        calculate_expr_distances(as);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
         m_list_false = new expr*[sz];
         //for (unsigned i = 0; i < sz; i++)
         //{
@@ -507,50 +494,38 @@ public:
         //}
 #endif
 
-#if _PAWS_
         for (unsigned i = 0; i < sz; i++)
         {
-            expr * e = g->form(i);
+            expr * e = as[i];
         	if (!m_weights.contains(e))
-        		m_weights.insert(e, _PAWS_INIT_);
+        		m_weights.insert(e, m_paws_init);
         }
-#endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-            setup_occs(g->form(i));
+            setup_occs(as[i]);
 #endif
 
-#if _UCT_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-#endif
+        m_touched = m_ucb_init ? as.size() : 1;
     }
 
-#if _PAWS_
     void increase_weight(expr * e)
     {
-        //printf("Increasing %d to", m_weights.find(e));
         m_weights.find(e)++;
-        //m_weights.find(e) *= 1.1;
-        //printf(" %d\n", m_weights.find(e));
     }
 
     void decrease_weight(expr * e)
     {
         unsigned old_weight = m_weights.find(e);
-        m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_;
-        //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1;
-        //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e));
+        m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init;
     }
 
     unsigned get_weight(expr * e)
-    //double get_weight(expr * e)
     {
         return m_weights.find(e);
     }
-#endif
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
     void make_assertion(expr * e)
     {
         if (m_where_false.contains(e))
@@ -683,7 +658,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(goal_ref const & g) {
+    void randomize(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -695,15 +670,9 @@ public:
         }
 
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
-
-#if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
-#endif
     }              
 
-    void reset(goal_ref const & g) {
+    void reset(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -711,15 +680,8 @@ public:
             set_value(it->m_value, temp);
             m_mpz_manager.del(temp);
         }
-
-#if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
-#endif
     }              
 
-#if _EARLY_PRUNE_
     void setup_occs(expr * n, bool negated = false) {
         if (m_manager.is_bool(n))
         {
@@ -752,7 +714,6 @@ public:
         else
             NOT_IMPLEMENTED_YET();
     }
-#endif
 
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
@@ -770,57 +731,29 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            // Andreas: Seems to have no effect. Probably it does not even occur.
-#if _SCORE_AND_AVG_
+            /* Andreas: Seems to have no effect. But maybe you want to try it again at some point.
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
-#if _DIRTY_UP_
-                sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
                 sum += get_score(args[i]);
-#endif
-            res = sum / (double) a->get_num_args();
-#else
+            res = sum / (double) a->get_num_args(); */
             double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
-#if _DIRTY_UP_
-                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
                 double cur = get_score(args[i]);
-#endif
                 if (cur < min) min = cur;
             }
             res = min;
-#endif
         }
         else if (m_manager.is_or(n)) {
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
             // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
-#if _SCORE_OR_MUL_
-            double inv = 1.0;
-            for (unsigned i = 0; i < a->get_num_args(); i++) {
-#if _DIRTY_UP_
-                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
-                double cur = get_score(args[i]);
-#endif
-                inv *= (1.0 - get_score(args[i]));
-            }
-            res = 1.0 - inv;
-#else
             double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
-#if _DIRTY_UP_
-                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
                 double cur = get_score(args[i]);
-#endif
                 if (cur > max) max = cur;
             }
             res = max;
-#endif
         }
         else if (m_manager.is_ite(n)) {
             SASSERT(!negated);
@@ -855,24 +788,14 @@ public:
                 m_mpz_manager.bitwise_xor(v0, v1, diff);
                 unsigned hamming_distance = 0;
                 unsigned bv_sz = m_bv_util.get_bv_size(arg0);
-                #if 1 // unweighted hamming distance
+                // unweighted hamming distance
                 while (!m_mpz_manager.is_zero(diff)) {
-                    //m_mpz_manager.set(diff_m1, diff);
-                    //m_mpz_manager.dec(diff_m1);
-                    //m_mpz_manager.bitwise_and(diff, diff_m1, diff);
-                    //hamming_distance++;
                     if (!m_mpz_manager.is_even(diff)) {
                         hamming_distance++;
                     }
                     m_mpz_manager.machine_div(diff, m_two, diff);
                 }
                 res = 1.0 - (hamming_distance / (double) bv_sz);
-                #else                    
-                rational r(diff);
-                r /= m_powers(bv_sz);
-                double dbl = r.get_double();
-                res = (dbl < 0.0) ? 1.0 : (dbl > 1.0) ? 0.0 : 1.0 - dbl;
-                #endif
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << " ; HD = " << hamming_distance << 
                                         " ; SZ = " << bv_sz << std::endl; );                    
@@ -891,205 +814,36 @@ public:
 
             if (negated) {
                 if (m_mpz_manager.gt(x, y))
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(x, y, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-/*                  mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_gt = 0;
-                    unsigned curr_gt = 0;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 1;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 0;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
-                    m_mpz_manager.del(x_copy);
-                    m_mpz_manager.del(y_copy);*/
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);                            
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));                            
-                    double dbl = 1.0 - n.get_double();
+                    double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
-                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
             }
             else {
                 if (m_mpz_manager.le(x, y))                        
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(y, x, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-/*                  mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_le = 1;
-                    unsigned curr_le = 1;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 0;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 1;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));
-                    double dbl = 1.0 - n.get_double();
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    double dbl = n.get_double();
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
             }
             TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                     m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
         }
-/*        else if (m_bv_util.is_bv_sle(n)) { // x <= y
-            app * a = to_app(n);
-            SASSERT(a->get_num_args() == 2);
-            const mpz & x = get_value(a->get_arg(0));
-            const mpz & y = get_value(a->get_arg(1));
-            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
-
-            mpz x_unsigned;
-            mpz y_unsigned;
-            const mpz & p = m_powers(bv_sz);
-            const mpz & p_half = m_powers(bv_sz-1);
-            if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } 
-            if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); }                 
-
-            if (negated) {
-                if (x_unsigned > y_unsigned)
-                    res = 1.0; 
-                else {
-                    mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_gt = 0;
-                    unsigned curr_gt = 0;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 1;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 0;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
-                    m_mpz_manager.del(x_copy);
-                    m_mpz_manager.del(y_copy);
-                }
-            }
-            else {
-                if (x_unsigned <= y_unsigned)                        
-                    res = 1.0; 
-                else {
-                    mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_le = 1;
-                    unsigned curr_le = 1;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 0;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 1;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);
-                }
-            }
-            TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
-                                    m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
-
-            m_mpz_manager.del(x_unsigned);
-            m_mpz_manager.del(y_unsigned);
-        }*/
-      else if (m_bv_util.is_bv_sle(n)) { // x <= y
+        else if (m_bv_util.is_bv_sle(n)) { // x <= y
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 2);
             mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0)));
@@ -1102,61 +856,32 @@ public:
 
             if (negated) {
                 if (x > y)
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(x, y, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);
                     rational n(diff);
                     n /= p;
-                    double dbl = 1.0 - n.get_double();
-                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    double dbl = n.get_double();
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
             else {
                 if (x <= y)
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(y, x, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
                     SASSERT(!m_mpz_manager.is_neg(diff));
                     rational n(diff);
                     n /= p;
-                    double dbl = 1.0 - n.get_double();
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    double dbl = n.get_double();
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
@@ -1171,11 +896,7 @@ public:
             expr * child = a->get_arg(0);
             if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
                 NOT_IMPLEMENTED_YET();
-#if _DIRTY_UP_
-            res = is_top_expr(child) ? 0.0 : score_bool(child, true);
-#else
             res = score_bool(child, true);
-#endif
         }
         else if (m_manager.is_distinct(n)) {
             app * a = to_app(n);
@@ -1199,25 +920,11 @@ public:
 
         SASSERT(res >= 0.0 && res <= 1.0);
 
-#if _WEIGHT_DIST_
         app * a = to_app(n);
         family_id afid = a->get_family_id();
 
         if (afid == m_bv_util.get_family_id())
-#endif
-#if _WEIGHT_DIST_ == 1
-#if _WEIGHT_TOGGLE_
-        if (res < 1.0) res *= m_weight_dist_factor;
-#else
-        if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
-#endif
-#elif _WEIGHT_DIST_ == 2
-        res *= res;
-#elif _WEIGHT_DIST_ == 3
-        if (res < 1.0) res = 0.0;
-#elif _WEIGHT_DIST_ == 4
-        if (res < 1.0) res *= m_weight_dist_factor;
-#endif
+            if (res < 1.0) res *= m_scale_unsat;
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
@@ -1268,33 +975,6 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-    expr * get_unsat_expression(expr * e) {
-        if (m_manager.is_bool(e)) {
-            if (m_manager.is_and(e) || m_manager.is_or(e)) {
-                app * a = to_app(e);
-                expr * const * args = a->get_args();
-                // Andreas: might be used for guided branching
-                //for (unsigned i = 0; i < a->get_num_args(); i++) {
-                    //double cur = get_score(args[i]);
-                //}
-                // Andreas: A random number is better here since reusing flip will cause patterns.
-                unsigned int sz = a->get_num_args();
-                unsigned int pos = get_random_uint(16) % sz;
-                for (unsigned int i = pos; i < sz; i++) {
-                    expr * q = args[i];
-                    if (m_mpz_manager.neq(get_value(q), m_one))
-                        return get_unsat_expression(q);
-                }
-                for (unsigned int i = 0; i < pos; i++) {
-                    expr * q = args[i];
-                    if (m_mpz_manager.neq(get_value(q), m_one))
-                        return get_unsat_expression(q);
-                }
-            }
-        }
-        return e;
-    }
-
     ptr_vector<func_decl> & get_constants(expr * e) {
         ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
         unsigned sz = this_decls.size();
@@ -1306,13 +986,17 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
-        if (sz == 1)
-            return get_constants();
+    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as) {
+        unsigned sz = as.size();
+        if (sz == 1) {
+            if (m_mpz_manager.neq(get_value(as[0]), m_one))
+                return get_constants();
+        }
+
         m_temp_constants.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * q = g->form(i);
+            expr * q = as[i];
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -1326,35 +1010,6 @@ public:
         return m_temp_constants;
     }
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
-            for (unsigned i = pos; i < sz; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-                    return q;
-            }
-            for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-                    return q;
-            }
-            return 0;
-    }
-
-    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-            expr * q = get_unsat_assertion(g, sz, pos);
-            // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
-            if (!q)
-                return m_temp_constants;
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
-            unsigned sz2 = this_decls.size();
-            for (unsigned j = 0; j < sz2; j++) {
-                func_decl * fd = this_decls[j];
-                if (!m_temp_constants.contains(fd))
-                    m_temp_constants.push_back(fd);
-            }
-            return m_temp_constants;
-    }
-
     ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
             if (!e || m_temp_constants.size())
                 return m_temp_constants;
@@ -1368,420 +1023,89 @@ public:
             return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & go_deeper(expr * e) {
-            if (m_manager.is_bool(e)) {
-                if (m_manager.is_and(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    // Andreas: might be used for guided branching
-                    //for (unsigned i = 0; i < a->get_num_args(); i++) {
-                        //double cur = get_score(args[i]);
-                    //}
-                    // Andreas: A random number is better here since reusing flip will cause patterns.
-                    unsigned int sz = a->get_num_args();
-                    unsigned int pos = get_random_uint(16) % sz;
-                    for (unsigned int i = pos; i < sz; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                    for (unsigned int i = 0; i < pos; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                }
-                else if (m_manager.is_or(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    unsigned int sz = a->get_num_args();
-                    unsigned int pos = get_random_uint(16) % sz;
-                    for (unsigned int i = pos; i < sz; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                    for (unsigned int i = 0; i < pos; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                }
-            }
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
-            unsigned sz2 = this_decls.size();
-            for (unsigned j = 0; j < sz2; j++) {
-                func_decl * fd = this_decls[j];
-                if (!m_temp_constants.contains(fd))
-                    m_temp_constants.push_back(fd);
-            }
-            return m_temp_constants;
-    }
+    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as) {
+        if (m_walksat)
+        {
+            expr * e = get_unsat_assertion(as);
 
-    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-        expr * q = get_unsat_assertion(g, sz, pos);
-        if (!q)
-            return m_temp_constants;
-
-        return go_deeper(q);
-    }
-
-    void go_deeper_only(expr * e) {
-            //if (m_manager.is_bool(e)) {
-                if (m_manager.is_and(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    unsigned int sz = a->get_num_args();
-                    unsigned cnt_unsat = 0, pos = -1;
-                    for (unsigned int i = 0; i < sz; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-                        //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q);
-                    }
-                    go_deeper(args[pos]);
-                }
-                else if (m_manager.is_or(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    unsigned int sz = a->get_num_args();
-                    for (unsigned int i = 0; i < sz; i++) {
-                        expr * q = args[i];
-                        go_deeper(q);
-                    }
-                }
-            //}
-                else
-                {
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
-            unsigned sz2 = this_decls.size();
-            for (unsigned j = 0; j < sz2; j++) {
-                func_decl * fd = this_decls[j];
-                if (!m_temp_constants.contains(fd))
-                    m_temp_constants.push_back(fd);
-            }
-                }
-    }
-
-    ptr_vector<func_decl> & get_unsat_constants_only(expr * e) {
-            if (e && !m_temp_constants.size())
-                go_deeper_only(e);
-
-            return m_temp_constants;
-    }
-
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
-
-        if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            if (!e)
             {
                 m_temp_constants.reset();
                 return m_temp_constants;
             }
-            else
-                return get_constants();
-        }
-        else {
-            m_temp_constants.reset();
-#if _FOCUS_ == 1
-#if _UCT_
-            unsigned pos = -1;
-            value_score vscore;
-#if _PROBABILISTIC_UCT_
-            double sum_score = 0.0;
-            unsigned start_index = get_random_uint(16) % sz;
 
-            for (unsigned i = start_index; i < sz; i++)
-            {
-                expr * e = g->form(i);
-                vscore = m_scores.find(e);
-
-#if _PROBABILISTIC_UCT_ == 2
-                double q = vscore.score * vscore.score; 
-#else
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                    sum_score += q;
-                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                        pos = i;
-                }	
-            }
-            for (unsigned i = 0; i < start_index; i++)
-            {
-                expr * e = g->form(i);
-                vscore = m_scores.find(e);
-#if _PROBABILISTIC_UCT_ == 2
-                double q = vscore.score * vscore.score; 
-#else
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                    sum_score += q;
-                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                        pos = i;
-                }	
-            }
-#else
-            double max = -1.0;
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-//            for (unsigned i = 0; i < m_where_false.size(); i++) {
-//                expr * e = m_list_false[i];
-                vscore = m_scores.find(e);
-#if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); 
-#elif _UCT_ == 2
-                double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
-#elif _UCT_ == 3
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
-#endif
-                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
-            }
-#endif
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-
-#if _UCT_ == 1 || _UCT_ == 3
-            m_scores.find(g->form(pos)).touched++;
-            m_touched++;
-#elif _UCT_ == 2
-            m_scores.find(g->form(pos)).touched = flip; 
-#endif
-            expr * e = g->form(pos);
-//            expr * e = m_list_false[pos];
-
-#elif _BFS_ == 3
-            unsigned int pos = -1;
-            double max = -1.0;
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                double q = get_score(e);
-                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
-            }
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-            expr * e = g->form(pos);
-#elif _BFS_ == 2
-            unsigned int pos = -1;
-            double min = 2.0;
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                double q = get_score(e);
-                if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
-            }
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-            expr * e = g->form(pos);
-#elif _BFS_ == 1
-            // I guess it was buggy ...
-            // unsigned int pos = flip % m_constants.size();
-            unsigned int pos = flip % sz;
-            expr * e = get_unsat_assertion(g, sz, pos);
-#elif _UNIFORM_RANDOM_
-            unsigned cnt_unsat = 0, pos = -1;
-            for (unsigned i = 0; i < sz; i++)
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-            expr * e = g->form(pos);
-#elif _REAL_RS_
-            //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-            //expr * e = get_unsat_assertion(g, sz, pos);
-            //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-            sz = m_where_false.size();
-            if (sz == 0)
-                return m_temp_constants;
-            expr * e = m_list_false[get_random_uint(16) % sz];
-#elif _REAL_PBFS_
-            //unsigned pos = m_false_list[flip % m_cnt_false];
-            //expr * e = get_unsat_assertion(g, sz, pos);
-            //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-            sz = m_where_false.size();
-            if (sz == 0)
-                return m_temp_constants;
-            else
-                expr * e = m_list_false[flip % sz];
-#else
-            // I guess it was buggy ...
-            // unsigned int pos = get_random_uint(16) % m_constants.size();
-            unsigned int pos = get_random_uint(16) % sz;
-            expr * e = get_unsat_assertion(g, sz, pos);
-#endif
             return get_unsat_constants_walksat(e);
-#elif _FOCUS_ == 2
-#if _BFS_
-            // I guess it was buggy ...
-            // unsigned int pos = flip % m_constants.size();
-            unsigned int pos = flip % sz;
-#else
-            // I guess it was buggy ...
-            // unsigned int pos = get_random_uint(16) % m_constants.size();
-            unsigned int pos = get_random_uint(16) % sz;
-#endif
-            return get_unsat_constants_crsat(g, sz, pos);
-#else
-            return get_unsat_constants_gsat(g, sz);
-#endif
         }
+        else
+            return get_unsat_constants_gsat(as);
     }
     
-    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
-
+    expr * get_unsat_assertion(ptr_vector<expr> const & as) {
+        unsigned sz = as.size();
         if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(g->form(0)), m_zero))
-                return g->form(0);
+            if (m_mpz_manager.neq(get_value(as[0]), m_one))
+                return as[0];
             else
                 return 0;
         }
-
         m_temp_constants.reset();
-#if _FOCUS_ == 1
-#if _UCT_
+
         unsigned pos = -1;
-        value_score vscore;
-#if _PROBABILISTIC_UCT_
-        double sum_score = 0.0;
-        unsigned start_index = get_random_uint(16) % sz;
-            
-        for (unsigned i = start_index; i < sz; i++)
+        if (m_ucb)
         {
-            expr * e = g->form(i);
-            vscore = m_scores.find(e);
-#if _PROBABILISTIC_UCT_ == 2
-            double q = vscore.score * vscore.score + _UCT_EPS_; 
-#else
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                sum_score += q;
-                if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                    pos = i;
-            }	
-        }
-        for (unsigned i = 0; i < start_index; i++)
-        {
-            expr * e = g->form(i);
-            vscore = m_scores.find(e);
-#if _PROBABILISTIC_UCT_ == 2
-            double q = vscore.score * vscore.score + _UCT_EPS_; 
-#else
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                sum_score += q;
-                if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                    pos = i;
-            }	
-        }
-#else
-        double max = -1.0;
+            value_score vscore;
+            double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
-#if _UCT_ == 1
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
-#elif _UCT_ == 2
-            double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
-#elif _UCT_ == 3
+                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+#if _UCT_ == 3
             double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
-            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-#endif
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
+            if (pos == static_cast<unsigned>(-1))
+                return 0;
 
-#if _UCT_ == 1 || _UCT_ == 3
-        m_scores.find(g->form(pos)).touched++;
-        m_touched++;
-#elif _UCT_ == 2
-        m_scores.find(g->form(pos)).touched = flip; 
-#endif
+            m_scores.find(as[pos]).touched++;
+            m_touched++;
 //        return m_list_false[pos];
-        return g->form(pos);
-
-#elif _BFS_ == 3
-        unsigned int pos = -1;
-        double max = -1.0;
-        for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
-               double q = get_score(e);
-            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
-        return g->form(pos);
-#elif _BFS_ == 2
-        unsigned int pos = -1;
-        double min = 2.0;
-        for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
-               double q = get_score(e);
-            if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
         }
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
-        return g->form(pos);
-#elif _BFS_ == 1
-        unsigned int pos = flip % sz;
-        return get_unsat_assertion(g, sz, pos);
-#elif _UNIFORM_RANDOM_
-        unsigned cnt_unsat = 0, pos = -1;
-        for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
-        return g->form(pos);
-#elif _REAL_RS_
+        else
+        {
+            unsigned cnt_unsat = 0;
+            for (unsigned i = 0; i < sz; i++)
+                if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+            if (pos == static_cast<unsigned>(-1))
+                return 0;
+        }
+        
+        return as[pos];
+#if _REAL_RS_
         //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-        //expr * e = get_unsat_assertion(g, sz, pos);
         //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
         sz = m_where_false.size();
         if (sz == 0)
             return 0;
         return m_list_false[get_random_uint(16) % sz];
-#elif _REAL_PBFS_
-        //unsigned pos = m_false_list[flip % m_cnt_false];
-        //expr * e = get_unsat_assertion(g, sz, pos);
-        //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-        sz = m_where_false.size();
-        if (sz == 0)
-            return0;
-        else
-            return m_list_false[flip % sz];
-#else
-        unsigned int pos = get_random_uint(16) % sz;
-        return get_unsat_assertion(g, sz, pos);
-#endif
-        return g->form(pos);
-#elif _FOCUS_ == 2
-#if _BFS_
-        unsigned int pos = flip % sz;
-#else
-        unsigned int pos = get_random_uint(16) % sz;
-#endif
-        return get_unsat_constants_crsat(g, sz, pos);
 #endif
     }
 
-    expr * get_new_unsat_assertion(goal_ref const & g, expr * e) {
-        unsigned sz = g->size();
-
+    expr * get_new_unsat_assertion(ptr_vector<expr> const & as, expr * e) {
+        unsigned sz = as.size();
         if (sz == 1)
             return 0;
-
         m_temp_constants.reset();
-
+        
         unsigned cnt_unsat = 0, pos = -1;
         for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i;	
+            if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i;	
 
         if (pos == static_cast<unsigned>(-1))
             return 0;
-        return g->form(pos);
+        return as[pos];
     }
 };
 

From 39ea6234a4ae1b3588d1c4b6750c21382cae6b4d Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 01:07:30 +0100
Subject: [PATCH 053/108] Fixed bug with VNS repick.

---
 src/tactic/sls/sls_compilation_settings.h |  2 +-
 src/tactic/sls/sls_engine.cpp             | 22 +++++++++++++++++-----
 src/tactic/sls/sls_tracker.h              |  7 ++++---
 3 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 9add78daa..a649bc9ed 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -23,7 +23,7 @@ Notes:
 #define _SLS_COMPILATION_SETTINGS_H_
 
 // shall we use addition/subtraction?
-#define _USE_ADDSUB_ 0
+#define _USE_ADDSUB_ 1
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index c240a0c51..af8ae1df2 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -68,6 +68,12 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_base = p.restart_base();
     m_restart_next = m_restart_base;
     m_restart_init = p.restart_init();
+
+    // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
+    if (m_walksat_repick && !m_walksat)
+        NOT_IMPLEMENTED_YET();
+    if (m_vns_repick && !m_walksat)
+        NOT_IMPLEMENTED_YET();
 }
 
 void sls_engine::checkpoint() {
@@ -435,19 +441,25 @@ lbool sls_engine::search() {
         if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
             score = find_best_move_mc(to_evaluate, score, new_const, new_value);
    
-        /*if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
+        if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
         {
-            expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e);
+            expr * q = m_tracker.get_new_unsat_assertion(m_assertions);
             if (q)
             {
-                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q);
                 score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move);
+
+                if (new_const != static_cast<unsigned>(-1)) {
+                    func_decl * fd = to_evaluate2[new_const];
+                    score = serious_score(fd, new_value);
+                    continue;
+                }
             }
-        }*/
+        }
 
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
-            if (m_walksat && m_walksat_repick)
+            if (m_walksat_repick)
                 m_evaluator.randomize_local(m_assertions);
             else
                 m_evaluator.randomize_local(to_evaluate);
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 65011dc8d..7b48057d4 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -76,7 +76,7 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
-
+    unsigned              m_last_pos;
     unsigned              m_walksat;
     unsigned              m_ucb;
     double                m_ucb_constant;
@@ -1082,6 +1082,7 @@ public:
                 return 0;
         }
         
+        m_last_pos = pos;
         return as[pos];
 #if _REAL_RS_
         //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
@@ -1093,7 +1094,7 @@ public:
 #endif
     }
 
-    expr * get_new_unsat_assertion(ptr_vector<expr> const & as, expr * e) {
+    expr * get_new_unsat_assertion(ptr_vector<expr> const & as) {
         unsigned sz = as.size();
         if (sz == 1)
             return 0;
@@ -1101,7 +1102,7 @@ public:
         
         unsigned cnt_unsat = 0, pos = -1;
         for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i;	
+            if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
 
         if (pos == static_cast<unsigned>(-1))
             return 0;

From b5a9e0a1f5ab1cf5df67baa068eec0963df55be2 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 16:10:44 +0100
Subject: [PATCH 054/108] Backup before I touch early pruning ...

---
 src/tactic/sls/sls_compilation_settings.h |  3 ---
 src/tactic/sls/sls_engine.cpp             | 30 +++++++++++++----------
 src/tactic/sls/sls_engine.h               |  1 +
 src/tactic/sls/sls_evaluator.h            |  4 +--
 src/tactic/sls/sls_tracker.h              |  9 -------
 5 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index a649bc9ed..5c837b4b2 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,9 +22,6 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
 
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index af8ae1df2..5d4df237e 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -61,6 +61,7 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_walksat = p.walksat();
     m_walksat_repick = p.walksat_repick();
     m_paws_sp = p.paws_sp();
+    m_paws = m_paws_sp < 1024;
     m_wp = p.wp();
     m_vns_mc = p.vns_mc();
     m_vns_repick = p.vns_repick();
@@ -173,7 +174,6 @@ bool sls_engine::what_if(
 
     // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
-        m_tracker.reset_equal_scores();
         best_score = r;
         best_const = fd_inx;
         m_mpz_manager.set(best_value, temp);
@@ -244,16 +244,12 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
     else
     {
-#if _USE_ADDSUB_
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
         move_type mt = (move_type)rnd_mv;
 
         // inversion doesn't make sense, let's do a flip instead.
         if (mt == MV_INV) mt = MV_FLIP;
-#else
-        move_type mt = MV_FLIP;
-#endif
         unsigned bit = 0;
 
         switch (mt)
@@ -308,8 +304,9 @@ double sls_engine::find_best_move(
     unsigned bv_sz;
     double new_score = score;
 
-    m_tracker.reset_equal_scores();
-
+    //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size();
+    //for (unsigned j = 0; j < to_evaluate.size(); j++) {
+        //unsigned i = (j + offset) % to_evaluate.size();
     for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
@@ -328,7 +325,6 @@ double sls_engine::find_best_move(
         }
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
@@ -341,7 +337,6 @@ double sls_engine::find_best_move(
                 if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
-#endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
             if (what_if(fd, i, temp, new_score, best_const, best_value))
@@ -418,7 +413,7 @@ lbool sls_engine::search() {
 #if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
-        
+        // get candidate variables
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
         {
@@ -426,6 +421,7 @@ lbool sls_engine::search() {
             goto bailout;
         }
 
+        // random walk with probability wp / 1024
         if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
             mk_random_move(to_evaluate);
@@ -436,14 +432,18 @@ lbool sls_engine::search() {
         old_score = score;
         new_const = (unsigned)-1;
 
+        // find best increasing move
         score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 
+        // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously
         if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
             score = find_best_move_mc(to_evaluate, score, new_const, new_value);
    
+        // repick assertion if no increasing move was found previously
         if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
         {
             expr * q = m_tracker.get_new_unsat_assertion(m_assertions);
+            // only apply if another unsatisfied assertion actually exists
             if (q)
             {
                 ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q);
@@ -457,6 +457,7 @@ lbool sls_engine::search() {
             }
         }
 
+        // randomize if no increasing move was found
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
             if (m_walksat_repick)
@@ -466,16 +467,19 @@ lbool sls_engine::search() {
 
             score = m_tracker.get_top_sum() / m_assertions.size();
 
-            if (m_paws_sp < 1024)
+            // update assertion weights if a weigthing is enabled (sp < 1024)
+            if (m_paws)
             {
                 for (unsigned i = 0; i < sz; i++)
                 {
                     expr * q = m_assertions[i];
+                    // smooth weights with probability sp / 1024
                     if (m_tracker.get_random_uint(10) < m_paws_sp)
                     {
                         if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
                             m_tracker.decrease_weight(q);
                     }
+                    // increase weights otherwise
                     else
                     {
                         if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
@@ -484,6 +488,7 @@ lbool sls_engine::search() {
                 }
             }
         }
+        // otherwise, apply most increasing move
         else {
             func_decl * fd = to_evaluate[new_const];
             score = serious_score(fd, new_value);
@@ -507,7 +512,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     for (unsigned i = 0; i < g->size(); i++)
         assert_expr(g->form(i));    
 
-    verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
 
@@ -570,7 +574,7 @@ inline unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_next)
     {
-        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter.
+        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter.
         I leave the other versions as comments in case you want to try it again somewhen.
 #if _RESTART_SCHEME_ == 5
         m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index ff0e55f24..94f3fa626 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -76,6 +76,7 @@ protected:
     unsigned        m_wp;
     unsigned        m_vns_mc;
     unsigned        m_vns_repick;
+    unsigned        m_paws;
     unsigned        m_paws_sp;
     unsigned        m_restart_base;
     unsigned        m_restart_next;
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 37bfa5a2d..200a0e380 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -37,9 +37,7 @@ class sls_evaluator {
     powers              & m_powers;
     expr_ref_buffer       m_temp_exprs;
     vector<ptr_vector<expr> > m_traversal_stack;
-#if _EARLY_PRUNE_
     vector<ptr_vector<expr> > m_traversal_stack_bool;
-#endif
 
 public:
     sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : 
@@ -753,7 +751,7 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-                // should always have uplinks ...
+                // Andreas: Should actually always have uplinks ...
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 7b48057d4..a815c9ad3 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -92,7 +92,6 @@ private:
 #endif
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
-    unsigned              m_equal_scores;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -148,14 +147,6 @@ public:
         return sum / count;   
     }
 
-    void reset_equal_scores() {
-        m_equal_scores = 1;
-    }
-
-    unsigned inc_equal_scores() {
-        return ++m_equal_scores;
-    }
-
     inline void adapt_top_sum(expr * e, double add, double sub) {
         m_top_sum += m_weights.find(e) * (add - sub);
     }

From c4fb21cca1e1d01cddb2690bc3fa6a91746f36a5 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Wed, 23 Apr 2014 14:52:18 +0100
Subject: [PATCH 055/108] Moved parameters to the right file. Almost clean.

---
 src/tactic/sls/sls_compilation_settings.h |  5 +--
 src/tactic/sls/sls_engine.cpp             | 38 +++++++++++------------
 src/tactic/sls/sls_engine.h               |  3 +-
 src/tactic/sls/sls_evaluator.h            |  5 ---
 src/tactic/sls/sls_params.pyg             | 20 ++++++++++--
 src/tactic/sls/sls_tracker.h              | 33 +++++++++-----------
 6 files changed, 52 insertions(+), 52 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 5c837b4b2..707802cf4 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,10 +22,7 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+// should we use unsat-structures as done in SLS 4 SAT?
 #define _REAL_RS_ 0
 
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 5d4df237e..a1c72609c 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -70,6 +70,8 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_next = m_restart_base;
     m_restart_init = p.restart_init();
 
+    m_early_prune = p.early_prune();
+
     // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
     if (m_walksat_repick && !m_walksat)
         NOT_IMPLEMENTED_YET();
@@ -117,7 +119,7 @@ double sls_engine::top_score() {
 
     m_tracker.set_top_sum(top_sum);
 
-    return top_sum / (double)sz;
+    return top_sum;
 }
 
 double sls_engine::rescore() {
@@ -129,21 +131,21 @@ double sls_engine::rescore() {
 double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return m_tracker.get_top_sum();
 }
 
 double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return m_tracker.get_top_sum();
 }
 
 double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
-        return (m_tracker.get_top_sum() / m_assertions.size());
+        return m_tracker.get_top_sum();
     else
-        return 0.0;
+        return -DBL_MAX;
 }
 
 // checks whether the score outcome of a given move is better than the previous score
@@ -160,11 +162,11 @@ bool sls_engine::what_if(
     m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 #endif
 
-#if _EARLY_PRUNE_
-    double r = incremental_score_prune(fd, temp);
-#else
-    double r = incremental_score(fd, temp);
-#endif   
+    double r;
+    if (m_early_prune)
+        r = incremental_score_prune(fd, temp);
+    else
+        r = incremental_score(fd, temp);
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
             " --> " << r << std::endl;);
@@ -342,11 +344,8 @@ double sls_engine::find_best_move(
             if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
         }
-
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
-        // Andreas: does not hold anymore now that we use top level score caching
-        //SASSERT(check == score);
+        incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -381,9 +380,8 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
                 }
             }
         }
-
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
+        incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -408,7 +406,10 @@ lbool sls_engine::search() {
         checkpoint();
         m_stats.m_moves++;
         if (m_stats.m_moves % m_restart_base == 0)
+        {
             m_tracker.ucb_forget(m_assertions);
+            //score = rescore();
+        }
 
 #if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
@@ -425,7 +426,7 @@ lbool sls_engine::search() {
         if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
             mk_random_move(to_evaluate);
-            score = m_tracker.get_top_sum() / sz;
+            score = m_tracker.get_top_sum();
             continue;
         }
 
@@ -465,7 +466,7 @@ lbool sls_engine::search() {
             else
                 m_evaluator.randomize_local(to_evaluate);
 
-            score = m_tracker.get_top_sum() / m_assertions.size();
+            score = m_tracker.get_top_sum();
 
             // update assertion weights if a weigthing is enabled (sp < 1024)
             if (m_paws)
@@ -513,7 +514,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         assert_expr(g->form(i));    
 
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-    verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
 
     lbool res = operator()();
 
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 94f3fa626..ac8610871 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -81,8 +81,7 @@ protected:
     unsigned        m_restart_base;
     unsigned        m_restart_next;
     unsigned        m_restart_init;
-
-    ptr_vector<mpz> m_old_values;
+    unsigned        m_early_prune;
 
     typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 200a0e380..e4cf3c466 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -554,9 +554,7 @@ public:
                 if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
-#if _EARLY_PRUNE_
                 m_tracker.set_score_prune(cur, new_score);
-#endif            
 
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -599,9 +597,6 @@ public:
                 if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
-#if _EARLY_PRUNE_
-                m_tracker.set_score_prune(cur, new_score);
-#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index cc3e05966..98875b20d 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -2,7 +2,21 @@ def_module_params('sls',
                   export=True,
                   description='Experimental Stochastic Local Search Solver (for QFBV only).',
                   params=(max_memory_param(),
-                          ('restarts', UINT, UINT_MAX, '(max) number of restarts'),
-                          ('plateau_limit', UINT, 10, 'pleateau limit'),
-			  ('random_seed', UINT, 0, 'random seed')
+						('max_restarts', UINT, UINT_MAX, 'maximum number of restarts'),
+						('walksat', BOOL, 1, 'use walksat assertion selection (instead of gsat)'),
+						('walksat_ucb', BOOL, 1, 'use bandit heuristic for walksat assertion selection (instead of random)'),
+						('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
+						('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'),
+						('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'),
+						('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'),
+						('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'),
+						('paws_init', UINT, 40, 'initial/minimum assertion weights'),
+						('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'),
+						('wp', UINT, 0, 'random walk with probability wp / 1024'),
+						('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'),
+						('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'),
+						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
+						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
+						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
+						('random_seed', UINT, 0, 'random seed')
 			  ))
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index a815c9ad3..507596273 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -44,11 +44,9 @@ class sls_tracker {
         unsynch_mpz_manager * m;
         mpz value;
         double score;
-#if _EARLY_PRUNE_
         double score_prune;
         unsigned has_pos_occ;
         unsigned has_neg_occ;
-#endif
         unsigned distance; // max distance from any root
         unsigned touched;
         value_score & operator=(const value_score & other) {
@@ -122,6 +120,7 @@ public:
         m_paws_init = p.paws_init();
     }
 
+    /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently.
     unsigned get_formula_size() {
         return m_scores.size();
     }
@@ -145,7 +144,7 @@ public:
         }
 
         return sum / count;   
-    }
+    }*/
 
     inline void adapt_top_sum(expr * e, double add, double sub) {
         m_top_sum += m_weights.find(e) * (add - sub);
@@ -417,6 +416,8 @@ public:
         }
     }
 
+    /* Andreas: Used this at some point to have values for the non-top-level expressions.
+                However, it did not give better performance but even cause some additional m/o - is not used currently.
     void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
         if (m_manager.is_and(e) || m_manager.is_or(e)) {
             app * a = to_app(e);
@@ -445,7 +446,7 @@ public:
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
-    }
+    }*/
 
     void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
@@ -455,8 +456,6 @@ public:
             expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
-            else
-                printf("this is already in ...\n");
             for_each_expr(proc, visited, e);
         }
 
@@ -464,7 +463,6 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = as[i];
-            // Andreas: Maybe not fully correct.
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -488,15 +486,16 @@ public:
         for (unsigned i = 0; i < sz; i++)
         {
             expr * e = as[i];
-        	if (!m_weights.contains(e))
+
+            // initialize weights
+            if (!m_weights.contains(e))
         		m_weights.insert(e, m_paws_init);
+
+            // positive/negative occurences used for early pruning
+            setup_occs(as[i]);
         }
 
-#if _EARLY_PRUNE_
-        for (unsigned i = 0; i < sz; i++)
-            setup_occs(as[i]);
-#endif
-
+        // initialize ucb total touched value (individual ones are always initialized to 1)
         m_touched = m_ucb_init ? as.size() : 1;
     }
 
@@ -738,7 +737,6 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
             double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
@@ -764,7 +762,6 @@ public:
             const mpz & v1 = get_value(arg1);
             
             if (negated) {                    
-                //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0;
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << std::endl; );
@@ -1051,10 +1048,8 @@ public:
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
-                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
-#if _UCT_ == 3
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
-#endif
+                //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); 
                 if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
             if (pos == static_cast<unsigned>(-1))

From b3924d85ed2e0db2daddc5ea31234685d9e84fc7 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Fri, 25 Apr 2014 13:56:15 +0100
Subject: [PATCH 056/108] Cleaned up final SLS version. Enjoy!

---
 src/tactic/sls/sls_compilation_settings.h |  28 ----
 src/tactic/sls/sls_engine.cpp             |  43 ++++--
 src/tactic/sls/sls_engine.h               |   2 +
 src/tactic/sls/sls_evaluator.h            |   8 +-
 src/tactic/sls/sls_params.pyg             |   6 +-
 src/tactic/sls/sls_tracker.h              | 153 ++++++++--------------
 6 files changed, 94 insertions(+), 146 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 707802cf4..e69de29bb 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -1,28 +0,0 @@
-/*++
-Copyright (c) 2014 Microsoft Corporation
-
-Module Name:
-
-    sls_compilation_constants.h
-
-Abstract:
-
-    Stochastic Local Search (SLS) compilation constants
-
-Author:
-
-    Christoph (cwinter) 2014-03-19
-
-Notes:
-
-    This file should go away completely once we have evaluated all options.
-
---*/
-
-#ifndef _SLS_COMPILATION_SETTINGS_H_
-#define _SLS_COMPILATION_SETTINGS_H_
-
-// should we use unsat-structures as done in SLS 4 SAT?
-#define _REAL_RS_ 0
-
-#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index a1c72609c..269790902 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -71,6 +71,8 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_init = p.restart_init();
 
     m_early_prune = p.early_prune();
+    m_random_offset = p.random_offset();
+    m_rescore = p.rescore();
 
     // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
     if (m_walksat_repick && !m_walksat)
@@ -174,6 +176,9 @@ bool sls_engine::what_if(
     m_mpz_manager.del(old_value);
 #endif
 
+    // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection.
+    // r += 0.0001 * m_tracker.get_random_uint(8);
+
     // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
         best_score = r;
@@ -248,9 +253,15 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     {
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+
+        // Andreas: The other option would be to scale the probability for flips according to the bit-width.
+        /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt);
+        rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3);
+        if (rnd_mv > 3) rnd_mv = 0; */
+
         move_type mt = (move_type)rnd_mv;
 
-        // inversion doesn't make sense, let's do a flip instead.
+        // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true?
         if (mt == MV_INV) mt = MV_FLIP;
         unsigned bit = 0;
 
@@ -306,10 +317,13 @@ double sls_engine::find_best_move(
     unsigned bv_sz;
     double new_score = score;
 
-    //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size();
-    //for (unsigned j = 0; j < to_evaluate.size(); j++) {
-        //unsigned i = (j + offset) % to_evaluate.size();
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
+    unsigned sz = to_evaluate.size();
+    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
+    for (unsigned j = 0; j < sz; j++) {
+        unsigned i = j + offset;
+        if (i >= sz) i -= sz;
+    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -361,7 +375,13 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
     unsigned bv_sz;
     double new_score = score;
 
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
+    unsigned sz = to_evaluate.size();
+    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
+    for (unsigned j = 0; j < sz; j++) {
+        unsigned i = j + offset;
+        if (i >= sz) i -= sz;
+    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -405,15 +425,16 @@ lbool sls_engine::search() {
     while (check_restart(m_stats.m_moves)) {
         checkpoint();
         m_stats.m_moves++;
+
+        // Andreas: Every base restart interval ...
         if (m_stats.m_moves % m_restart_base == 0)
         {
+            // ... potentially smooth the touched counters ...
             m_tracker.ucb_forget(m_assertions);
-            //score = rescore();
+            // ... or normalize the top-level score.
+            if (m_rescore) score = rescore();
         }
 
-#if _REAL_RS_
-        //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
         // get candidate variables
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
@@ -513,8 +534,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     for (unsigned i = 0; i < g->size(); i++)
         assert_expr(g->form(i));    
 
-    verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-
     lbool res = operator()();
 
     if (res == l_true) {
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index ac8610871..8158808fa 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -82,6 +82,8 @@ protected:
     unsigned        m_restart_next;
     unsigned        m_restart_init;
     unsigned        m_early_prune;
+    unsigned        m_random_offset;
+    unsigned        m_rescore;
 
     typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index e4cf3c466..61afb7457 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -22,7 +22,6 @@ Notes:
 
 #include"model_evaluator.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 #include"sls_tracker.h"
 
@@ -540,19 +539,16 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 
-#if _REAL_RS_
+                new_score = m_tracker.score(cur);
                 if (m_tracker.is_top_expr(cur))
                 {
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     if (m_mpz_manager.eq(new_value,m_one))
                         m_tracker.make_assertion(cur);
                     else
                         m_tracker.break_assertion(cur);
                 }
-#endif
 
-                new_score = m_tracker.score(cur);
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
 
diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index 98875b20d..ad7a22675 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -8,15 +8,19 @@ def_module_params('sls',
 						('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
 						('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'),
 						('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'),
+						('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'),
 						('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'),
 						('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'),
 						('paws_init', UINT, 40, 'initial/minimum assertion weights'),
 						('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'),
-						('wp', UINT, 0, 'random walk with probability wp / 1024'),
+						('wp', UINT, 100, 'random walk with probability wp / 1024'),
 						('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'),
 						('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'),
 						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
 						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
 						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
+						('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'),
+						('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'),
+						('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'),
 						('random_seed', UINT, 0, 'random seed')
 			  ))
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 507596273..4356bcc9b 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -80,14 +80,13 @@ private:
     double                m_ucb_constant;
     unsigned              m_ucb_init;
     double                m_ucb_forget;
+    double                m_ucb_noise;
     unsigned              m_touched;
     double                m_scale_unsat;
     unsigned              m_paws_init;
-#if _REAL_RS_
-    ptr_vector<expr>	  m_unsat_expr;
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
-#endif
+    unsigned              m_track_unsat;
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
 
@@ -116,8 +115,12 @@ public:
         m_ucb_constant = p.walksat_ucb_constant();
         m_ucb_init = p.walksat_ucb_init();
         m_ucb_forget = p.walksat_ucb_forget();
+        m_ucb_noise = p.walksat_ucb_noise();
         m_scale_unsat = p.scale_unsat();
         m_paws_init = p.paws_init();
+        // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy.
+        // If you want to use it, you will also need to change comments in the assertion selection.
+        m_track_unsat = 0;//p.track_unsat();
     }
 
     /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently.
@@ -254,53 +257,6 @@ public:
         return m_uplinks.find(n);
     }
 
-#if _REAL_RS_
-    void debug_real(goal_ref const & g, unsigned flip)
-    {
-        unsigned count = 0;
-        for (unsigned i = 0; i < g->size(); i++)
-        {
-            expr * e = g->form(i);
-            if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e))
-            {
-                printf("iteration %d: ", flip);
-                printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size());
-                exit(4);
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e))
-            {
-                printf("iteration %d: ", flip);
-                printf("form %d is unsat but not in unsat list\n", i);
-                exit(4);
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e))
-            {
-                unsigned pos = m_where_false.find(e);
-                expr * q = m_list_false[pos];
-                if (q != e)
-                {
-                    printf("iteration %d: ", flip);
-                    printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos);
-                    exit(4);
-                }
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero))
-                count++;
-        }
-
-        // should be true now that duplicate assertions are removed
-        if (count != m_where_false.size())
-        {
-                printf("iteration %d: ", flip);
-                printf("%d are unsat but list is of size %d\n", count, m_where_false.size());
-                exit(4);
-        }
-    }
-#endif
-
     inline void ucb_forget(ptr_vector<expr> & as) {
         if (m_ucb_forget < 1.0)
         {
@@ -474,14 +430,15 @@ public:
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
-#if _REAL_RS_
-        m_list_false = new expr*[sz];
-        //for (unsigned i = 0; i < sz; i++)
-        //{
-        //	if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-        //		break_assertion(g->form(i));
-        //}
-#endif
+        if (m_track_unsat)
+        {
+            m_list_false = new expr*[sz];
+            for (unsigned i = 0; i < sz; i++)
+            {
+        	    if (m_mpz_manager.eq(get_value(as[i]), m_zero))
+                    break_assertion(as[i]);
+            }
+        }
 
         for (unsigned i = 0; i < sz; i++)
         {
@@ -515,44 +472,36 @@ public:
         return m_weights.find(e);
     }
 
-#if _REAL_RS_
     void make_assertion(expr * e)
     {
-        if (m_where_false.contains(e))
+        if (m_track_unsat)
         {
-            unsigned pos = m_where_false.find(e);
-            m_where_false.erase(e);
-            if (pos != m_where_false.size())
+            if (m_where_false.contains(e))
             {
-                expr * q = m_list_false[m_where_false.size()];
-                m_list_false[pos] = q;
-                m_where_false.find(q) = pos;
-                //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos);
+                unsigned pos = m_where_false.find(e);
+                m_where_false.erase(e);
+                if (pos != m_where_false.size())
+                {
+                    expr * q = m_list_false[m_where_false.size()];
+                    m_list_false[pos] = q;
+                    m_where_false.find(q) = pos;
+                }
             }
-            //else
-                //printf("Erasing %d from %d to %d\n", e, pos);
-//			m_list_false[m_where_false.size()] = 0;
-//			printf("Going in %d\n", m_where_false.size());
         }
-        //if (m_unsat_expr.contains(e))
-            //m_unsat_expr.erase(e);
     }
 
     void break_assertion(expr * e)
     {
-        //printf("I'm broken... that's still fine.\n");
-        if (!m_where_false.contains(e))
+        if (m_track_unsat)
         {
-            //printf("This however is not so cool...\n");
-            unsigned pos = m_where_false.size();
-            m_list_false[pos] = e;
-            m_where_false.insert(e, pos);
-    //		printf("Going in %d\n", m_where_false.size());
+            if (!m_where_false.contains(e))
+            {
+                unsigned pos = m_where_false.size();
+                m_list_false[pos] = e;
+                m_where_false.insert(e, pos);
+            }
         }
-        //if (!m_unsat_expr.contains(e))
-            //m_unsat_expr.push_back(e);
     }
-#endif
 
     void show_model(std::ostream & out) {
         unsigned sz = get_num_constants();
@@ -1043,24 +992,38 @@ public:
         {
             value_score vscore;
             double max = -1.0;
+            // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit.
+            /* for (unsigned i = 0; i < m_where_false.size(); i++) {
+                expr * e = m_list_false[i]; */
             for (unsigned i = 0; i < sz; i++) {
                 expr * e = as[i];
-//            for (unsigned i = 0; i < m_where_false.size(); i++) {
-//                expr * e = m_list_false[i];
-                vscore = m_scores.find(e);
-                //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
-                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); 
-                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (m_mpz_manager.neq(get_value(e), m_one))
+                {
+                    vscore = m_scores.find(e);
+                    // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise.
+                    // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+                    double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); 
+                    if (q > max) { max = q; pos = i; }
+                }
             }
             if (pos == static_cast<unsigned>(-1))
                 return 0;
 
-            m_scores.find(as[pos]).touched++;
             m_touched++;
-//        return m_list_false[pos];
+            m_scores.find(as[pos]).touched++;
+            // Andreas: Also part of track_unsat data structures. Additionally disable the previous line!
+            /* m_last_pos = pos;
+            m_scores.find(m_list_false[pos]).touched++;
+            return m_list_false[pos]; */
         }
         else
         {
+            // Andreas: The track_unsat data structures for random assertion selection.
+            /* sz = m_where_false.size();
+            if (sz == 0)
+                return 0;
+            return m_list_false[get_random_uint(16) % sz]; */
+
             unsigned cnt_unsat = 0;
             for (unsigned i = 0; i < sz; i++)
                 if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
@@ -1070,14 +1033,6 @@ public:
         
         m_last_pos = pos;
         return as[pos];
-#if _REAL_RS_
-        //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-        //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-        sz = m_where_false.size();
-        if (sz == 0)
-            return 0;
-        return m_list_false[get_random_uint(16) % sz];
-#endif
     }
 
     expr * get_new_unsat_assertion(ptr_vector<expr> const & as) {

From e34b5edf27d91e5546264313c7027781dfac2c72 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 17:17:47 +0100
Subject: [PATCH 057/108] BVSLS comments

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_params.pyg | 2 +-
 src/tactic/sls/sls_tracker.h  | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index ad7a22675..bf5bd181a 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -19,7 +19,7 @@ def_module_params('sls',
 						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
 						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
 						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
-						('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'),
+						('random_offset', BOOL, 1, 'use random offset for candidate evaluation'),
 						('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'),
 						('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'),
 						('random_seed', UINT, 0, 'random seed')
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 4356bcc9b..d58f94af2 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -831,7 +831,9 @@ public:
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 1);
             expr * child = a->get_arg(0);
-            if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
+            // Precondition: Assertion set is in NNF.
+            // Also: careful about the unsat assertion scaling further down.
+            if (m_manager.is_and(child) || m_manager.is_or(child)) 
                 NOT_IMPLEMENTED_YET();
             res = score_bool(child, true);
         }

From a02c59c1bc76efe5c9905f073fd9ffcac2b7b617 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 18:03:35 +0100
Subject: [PATCH 058/108] removed unused file

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h | 0
 src/tactic/sls/sls_engine.cpp             | 1 -
 src/tactic/sls/sls_engine.h               | 1 -
 src/tactic/sls/sls_tracker.h              | 1 -
 4 files changed, 3 deletions(-)
 delete mode 100644 src/tactic/sls/sls_compilation_settings.h

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 269790902..67dba0237 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -27,7 +27,6 @@ Notes:
 #include"cooperate.h"
 #include"luby.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_params.hpp"
 #include"sls_engine.h"
 
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8158808fa..8a8a57e0e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -24,7 +24,6 @@ Notes:
 #include"model_converter.h"
 #include"goal.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_tracker.h"
 #include"sls_evaluator.h"
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index d58f94af2..186fae250 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -25,7 +25,6 @@ Notes:
 #include"bv_decl_plugin.h"
 #include"model.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 
 class sls_tracker {

From fc0cdcfd2968b95bce0c9aee9a4363b5e0b9af9b Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 18:11:30 +0100
Subject: [PATCH 059/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 186fae250..73355197a 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -25,6 +25,7 @@ Notes:
 #include"bv_decl_plugin.h"
 #include"model.h"
 
+#include"sls_params.hpp"
 #include"sls_powers.h"
 
 class sls_tracker {
@@ -1052,4 +1053,4 @@ public:
     }
 };
 
-#endif
\ No newline at end of file
+#endif

From 60753bf46b822191969e6cd70fbb9e3d1aec0d06 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 21:49:35 +0100
Subject: [PATCH 060/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8a8a57e0e..b056c438e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -136,8 +136,8 @@ protected:
 
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
 
-    //inline double get_restart_armin(unsigned cnt_restarts);    
-    inline unsigned check_restart(unsigned curr_value);
+    //double get_restart_armin(unsigned cnt_restarts);    
+    unsigned check_restart(unsigned curr_value);
 };
 
 #endif

From 54cd1ea5e6ae90e0150ca712d190594c3812e451 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 21:54:08 +0100
Subject: [PATCH 061/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 67dba0237..5b32e5790 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -16,6 +16,7 @@ Author:
 Notes:
 
 --*/
+#include<float.h>
 #include<iomanip>
 
 #include"map.h"

From 6b9c5dbfc061eaa40a2e3a02a9505119ec8b71e2 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 22:03:26 +0100
Subject: [PATCH 062/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 5b32e5790..c0c319ab4 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -581,7 +581,7 @@ lbool sls_engine::operator()() {
 }
 
 /* Andreas: Needed for Armin's restart scheme if we don't want to use loops.
-inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
+double sls_engine::get_restart_armin(unsigned cnt_restarts)
 {
     unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
     unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
@@ -589,7 +589,7 @@ inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
 }    
 */
 
-inline unsigned sls_engine::check_restart(unsigned curr_value)
+unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_next)
     {

From aa0980b83b8d981e754e738d18ea1036391806a1 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 11 Sep 2014 00:27:37 +0100
Subject: [PATCH 063/108] merge fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tactic.cpp | 1413 +--------------------------------
 1 file changed, 30 insertions(+), 1383 deletions(-)

diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 6e1102dd2..9bbed20bb 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,1378 +16,30 @@ Author:
 Notes:
 
 --*/
-#include<iomanip>
-#include"map.h"
 #include"nnf.h"
-#include"cooperate.h"
-#include"ast_smt2_pp.h"
-#include"ast_pp.h"
-#include"var_subst.h"
-#include"model_pp.h"
-#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
-#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"stopwatch.h"
 #include"propagate_values_tactic.h"
-#include"sls_tactic.h"
+#include"ctx_simplify_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"nnf_tactic.h"
-#include"luby.h"
-#include "ctx_simplify_tactic.h"
-
-// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
-// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
-#define _BFS_ 0
-
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
-#define _FOCUS_ 1
-
-// probability of choosing the same assertion again in the next step
-#define _PERC_STICKY_ 0
-
-// do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 1
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
-// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 4.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// should score of discunctions be calculated by multiplication of the inverse score rather than min?
-#define _SCORE_OR_MUL_ 0
-
-// do we use some kind of variable neighbourhood-search?
-// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
-#define _VNS_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no
-// 1 = yes, by multiplying it with some factor
-// 2 = yes, by squaring it
-// 3 = yes, by setting it to zero
-// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.5
-
-// shall we toggle the weight after each restart?
-#define _WEIGHT_TOGGLE_ 0
-
-// do we use intensification steps in local minima? if so, how many?
-#define _INTENSIFICATION_ 0
-#define _INTENSIFICATION_TRIES_ 0
-
-// what is the percentage of random moves in plateaus (instead of full randomization)?
-#define _PERC_PLATEAU_MOVES_ 0
-
-// shall we repick clause when randomizing in a plateau or use the current one?
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 20.0
-
-// is uct clause selection probabilistic similar to variable selection in sparrow?
-// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
-#define _PROBABILISTIC_UCT_ 0
-
-// additive constants for probabilistic uct > 0
-#define _UCT_EPS_ 0.0001
-
-// shall we reset _UCT_ touched values after restart?
-#define _UCT_RESET_ 0
-
-// do we gradually reduce the touched values of _UCT_?
-#define _UCT_FORGET_ 0
-#define _UCT_FORGET_FACTOR_ 0.5
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 0
-
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
-// shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 0
-
-// shall we try multiplication by 3?
-#define _USE_MUL3_ 0
-
-// shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 0
-
-// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 0
-
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
-#define _REAL_RS_ 0
-#define _REAL_PBFS_ 0
-
-// how many bits do we neglect in each iteration?
-#define _SKIP_BITS_ 0
-
-// when randomizing local, what is the probability for changing a single bit?
-// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
-#define _PERC_CHANGE_ 0
-
-// do we use random steps for noise?
-// 0 = no, 1 = randomize local, 2 = make random move
-#define _TYPE_RSTEP_ 0
-
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
-
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-
-#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
-    InvalidConfiguration;
-#endif
-#if (_PROBABILISTIC_UCT_ && !_UCT_)
-    InvalidConfiguration;
-#endif
-#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
-    InvalidConfiguration;
-#endif
-#if (_PERC_CHANGE_ == 50)
-    InvalidConfiguration;
-#endif
-#if (_PERC_STICKY_ && !_FOCUS_)
-    InvalidConfiguration;
-#endif
-
+#include"stopwatch.h"
+#include"sls_tactic.h"
 #include"sls_params.hpp"
-#include"sls_evaluator.h"
-#include"sls_tracker.h"
+#include"sls_engine.h"
 
-class sls_tactic : public tactic {
-    class stats {
-    public:
-        unsigned        m_restarts;
-        stopwatch       m_stopwatch;    
-        unsigned        m_full_evals;
-        unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
-
-        stats() :
-            m_restarts(0),
-            m_full_evals(0),
-            m_incr_evals(0),
-            m_moves(0),
-            m_umins(0),
-            m_mul2s(0),
-            m_mul3s(0),
-            m_div2s(0),
-            m_flips(0),
-            m_incs(0),
-            m_decs(0),
-            m_invs(0) {
-                m_stopwatch.reset();
-                m_stopwatch.start();
-            }
-        void reset() {
-            m_full_evals = m_flips = m_incr_evals = 0;
-            m_stopwatch.reset();
-            m_stopwatch.start();
-        }
-    };    
-
-    struct imp {       
-        ast_manager   & m_manager;
-        stats         & m_stats;
-        unsynch_mpz_manager m_mpz_manager;
-        powers          m_powers;
-        mpz             m_zero, m_one, m_two;            
-        bool            m_produce_models;
-        volatile bool   m_cancel;    
-        bv_util         m_bv_util;
-        sls_tracker     m_tracker;
-        sls_evaluator   m_evaluator;
-
-        unsigned		m_restart_limit;
-        unsigned        m_max_restarts;
-        unsigned        m_plateau_limit;
-
-        ptr_vector<mpz> m_old_values;
-        
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
-
-        imp(ast_manager & m, params_ref const & p, stats & s) : 
-            m_manager(m),
-            m_stats(s),
-            m_powers(m_mpz_manager),
-            m_zero(m_mpz_manager.mk_z(0)),
-            m_one(m_mpz_manager.mk_z(1)),
-            m_two(m_mpz_manager.mk_z(2)),
-            m_cancel(false),
-            m_bv_util(m),
-            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
-            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
-        {
-            updt_params(p);
-        }
-
-        ~imp() {
-            m_mpz_manager.del(m_zero);
-            m_mpz_manager.del(m_one);
-            m_mpz_manager.del(m_two);
-        }        
-
-        double get_restart_armin(unsigned cnt_restarts)
-        {
-            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-            //printf("armin: %f\n", pow(1.1, inner_id + 1));
-            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
-        }
-
-        inline unsigned check_restart(unsigned curr_value)
-        {
-            if (curr_value > m_restart_limit)
-            {
-#if _RESTART_SCHEME_ == 5
-                m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
-#elif _RESTART_SCHEME_ == 4
-                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
-#elif _RESTART_SCHEME_ == 3
-                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 2
-                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 1
-                if (m_stats.m_restarts & 1)
-                    m_restart_limit += _RESTART_LIMIT_;
-                else
-                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
-#else
-                    m_restart_limit += _RESTART_LIMIT_;
-#endif
-#if _WEIGHT_TOGGLE_
-                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-#endif
-                return 0;
-            }
-            return 1;
-        }
-
-        ast_manager & m() const { return m_manager; }
-
-        void set_cancel(bool f) { m_cancel = f; }
-        void cancel() { set_cancel(true); }
-        void reset_cancel() { set_cancel(false); }
-
-        static void collect_param_descrs(param_descrs & r) {
-            sls_params::collect_param_descrs(r);
-        }
-
-        void updt_params(params_ref const & _p) {
-            sls_params p(_p);
-            m_produce_models = _p.get_bool("model", false);
-            m_max_restarts = p.restarts();            
-            m_tracker.set_random_seed(p.random_seed());
-            m_plateau_limit = p.plateau_limit();
-        }
-
-        void checkpoint() { 
-            if (m_cancel)
-                throw tactic_exception(TACTIC_CANCELED_MSG);
-            cooperate("sls");
-        }
-
-        bool full_eval(goal_ref const & g, model & mdl) {
-            bool res = true;
-
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz && res; i++) {
-                checkpoint();
-                expr_ref o(m_manager);
-
-                if (!mdl.eval(g->form(i), o, true))
-                    exit(ERR_INTERNAL_FATAL);
-
-                res = m_manager.is_true(o.get());
-            }        
-
-            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
-
-            return res;
-        }
-
-        double top_score(goal_ref const & g) {
-            #if 0
-            double min = m_tracker.get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
-                double q = m_tracker.get_score(g->form(i));
-                if (q < min) min = q;
-            }
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                for (unsigned i = 0; i < sz; i++)
-                                    tout << " " << m_tracker.get_score(g->form(i));
-                                tout << " MIN: " << min << std::endl; );
-            return min;
-            #else
-            double top_sum = 0.0;
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                top_sum += m_tracker.get_score(e);
-            }
-
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                    for (unsigned i = 0; i < sz; i++)
-                                        tout << " " << m_tracker.get_score(g->form(i));
-                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
-
-#if _CACHE_TOP_SCORE_
-            m_tracker.set_top_sum(top_sum);
-#endif
-
-            return top_sum / (double) sz;
-            #endif
-        }
-
-        double rescore(goal_ref const & g) {
-            m_evaluator.update_all();
-            m_stats.m_full_evals++;
-            return top_score(g);
-        }
-
-        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.serious_update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-#if _EARLY_PRUNE_
-        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_stats.m_incr_evals++;
-            if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
-                return (m_tracker.get_top_sum() / g->size());
-#else
-                return top_score(g);
-#endif
-            else
-                return 0.0;
-        }
-#endif
-
-        // checks whether the score outcome of a given move is better than the previous score
-        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-
-            #ifdef Z3DEBUG
-            mpz old_value;
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-            #endif
-
-#if _EARLY_PRUNE_
-            double r = incremental_score_prune(g, fd, temp);
-#else
-            double r = incremental_score(g, fd, temp);
-#endif   
-            #ifdef Z3DEBUG
-            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
-                                        " --> " << r << std::endl; );
-        
-            m_mpz_manager.del(old_value);
-            #endif
-
-//            if (r >= best_score) {
-            if (r > best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // same as what_if, but only applied to the score of a specific atom, not the total score
-        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-            m_evaluator.update(fd, temp);
-            double r = m_tracker.get_score(e);
-            if (r >= best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.add(old_value, add_value, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-
-        }
-
-        // Andreas: do we really need all those temporary mpzs?
-        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.mul(old_value, m_two, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-        }
-
-        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            m_mpz_manager.div(old_value, m_two, result);
-        }
-
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
-            unsigned shift;        
-            m_mpz_manager.add(old_value, m_one, incremented);
-            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
-                m_mpz_manager.set(incremented, m_zero);
-        }
-
-        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
-            if (m_mpz_manager.is_zero(old_value)) {
-                m_mpz_manager.set(decremented, m_powers(bv_sz));
-                m_mpz_manager.dec(decremented);
-            }
-            else
-                m_mpz_manager.sub(old_value, m_one, decremented);
-        }
-
-        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
-            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
-        }
-
-        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
-            m_mpz_manager.set(flipped, m_zero);
-
-            if (m_bv_util.is_bv_sort(s)) {
-                mpz mask;
-                m_mpz_manager.set(mask, m_powers(bit));
-                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
-                m_mpz_manager.del(mask);
-            }
-            else if (m_manager.is_bool(s))
-                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
-            else
-                NOT_IMPLEMENTED_YET();
-        }
-
-        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
-        {
-            unsigned rnd_mv = 0;
-            unsigned ucc = unsat_constants.size(); 
-            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
-            func_decl * fd = unsat_constants[rc];
-
-            mpz new_value;
-
-            sort * srt = fd->get_range();
-            if (m_manager.is_bool(srt))
-                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-            else
-            {
-#if _USE_ADDSUB_
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-                move_type mt = (move_type) rnd_mv;
-
-                // inversion doesn't make sense, let's do a flip instead.
-                if (mt == MV_INV) mt = MV_FLIP;
-#else
-                mt = MV_FLIP;
-#endif
-                unsigned bit = 0;
-
-                switch (mt)
-                {
-                    case MV_FLIP: {
-                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
-                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                    break;
-                }
-                case MV_INC: 
-                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_DEC: 
-                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_INV:
-                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                default:
-                    NOT_IMPLEMENTED_YET();
-                }
-
-                TRACE("sls", tout << "Randomization candidates: ";
-                             for (unsigned i = 0; i < unsat_constants.size(); i++)
-                                 tout << unsat_constants[i]->get_name() << ", ";
-                             tout << std::endl;
-                             tout << "Random move: ";
-                             switch (mt) {
-                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                             }
-                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-            }
-
-            m_evaluator.update(fd, new_value);            
-            m_mpz_manager.del(new_value);
-        }
-
-        void mk_random_move(goal_ref const & g) {
-            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
-        }
-
-        // will use VNS to ignore some possible moves and increase the flips per second
-        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz, max_bv_sz = 0;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-                    // try to flip lsb
-                    mk_flip(srt, old_value, 0, temp);                
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = 0;
-                        move = MV_FLIP;
-                    }
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-
-            // we can either check the condition once in the beginning or check it repeatedly after every bit
-#if _VNS_ == 1
-            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
-#else
-            if (new_score <= score)
-            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
-#endif
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // What would happen if we flipped bit #j ?                
-                if (j < bv_sz)
-                {
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-            mpz temp2;
-#endif
-            unsigned bv_sz;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-#if _SKIP_BITS_
-                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
-#else
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-#endif
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-#endif
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-#if _USE_UNARY_MINUS_
-                    mk_inc(bv_sz, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_UMIN;
-#endif
-
-#if _USE_MUL2DIV2_
-                    // try multiplication by 2
-                    mk_mul2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_MUL2;
-
-#if _USE_MUL3_
-                    // try multiplication by 3
-                    mk_add(bv_sz, old_value, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_MUL3;
-#endif
-
-                    // try division by 2
-                    mk_div2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_DIV2;
-#endif
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                // Andreas: does not hold anymore now that we use top level score caching
-                //SASSERT(check == score);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-#if _USE_MUL3_
-            m_mpz_manager.del(temp2);
-#endif
-            return new_score;
-        }        
-
-        // same as find_best_move but only considers the score of the current expression instead of the overall score
-        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz;
-            double new_score = m_tracker.get_score(e);
-            // Andreas: tie breaking not implemented yet
-            // double tie_score = top_score(g);
-            for (unsigned i = 0; i < to_evaluate.size(); i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz; j++) {
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-                }
-
-                // reset to what it was before
-                m_evaluator.update(fd, old_value);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // first try of intensification ... does not seem to be efficient
-        bool handle_plateau(goal_ref const & g)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned pos = m_stats.m_moves % sz;
-#else
-            unsigned pos = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-            {
-                m_tracker.get_value(to_evaluate[i]);
-                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-            }            
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-            {
-                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
-                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    // Andreas: Actually this should never happen.
-                    NOT_IMPLEMENTED_YET();
-                } else {
-                    m_stats.m_moves++;
-                    func_decl * fd = to_evaluate[new_const];
-
-                    switch (move) {
-                    case MV_FLIP: m_stats.m_flips++; break;
-                    case MV_INC: m_stats.m_incs++; break;
-                    case MV_DEC: m_stats.m_decs++; break;
-                    case MV_INV: m_stats.m_invs++; break;
-                    case MV_UMIN: m_stats.m_umins++; break;
-                    case MV_MUL2: m_stats.m_mul2s++; break;
-                    case MV_MUL3: m_stats.m_mul3s++; break;
-                    case MV_DIV2: m_stats.m_div2s++; break;
-                    }
-                    
-                    m_evaluator.update(fd, new_value);
-                }
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
-
-            m_old_values.reset();
-
-            return 0;
-        }
-
-        // what_if version needed in the context of 2nd intensification try, combining local and global score
-        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
-                        double & best_score, mpz & best_value, unsigned i) {
-        
-            double global_score = incremental_score(g, fd, temp);
-            double local_score = m_tracker.get_score(e);
-            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
-
-            if (new_score >= best_score) {
-                best_score = new_score;
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // find_best_move version needed in the context of 2nd intensification try
-        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-        {
-            mpz old_value, temp;
-            double best_score = 0;
-
-            sort * srt = fd->get_range();
-            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
-                mk_flip(srt, old_value, j, temp);                
-                what_if(g, e, fd, temp, best_score, best_value, i); 
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-
-            return best_score;
-        }        
-
-        // second try to use intensification ... also not very effective
-        bool handle_plateau(goal_ref const & g, double old_score)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned new_const = m_stats.m_moves % sz;
-#else
-            unsigned new_const = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-
-            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-            func_decl * fd = to_evaluate[new_const];
-
-            mpz new_value;
-            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-            unsigned new_bit = 0;        
-            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-            
-            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-            {
-                new_score = find_best_move_local(g, q, fd, new_value, i);
-
-                m_stats.m_moves++;
-                m_stats.m_flips++;
-
-                global_score = incremental_score(g, fd, new_value);
-                local_score = m_tracker.get_score(q);
-
-                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            return 0;
-        }
-
-        // main search loop
-        lbool search(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            unsigned plateau_cnt = 0;
-
-            score = rescore(g);
-            unsigned sz = g->size();
-#if _PERC_STICKY_
-            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-
-#if _RESTARTS_ == 1
-            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 2
-            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 3
-            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#endif
-                checkpoint();
-                m_stats.m_moves++;
-
-#if _UCT_FORGET_
-                if (m_stats.m_moves % _UCT_FORGET_ == 0)
-                    m_tracker.uct_forget(g);
-#endif
-
-#if _REAL_RS_ || _REAL_PBFS_
-                //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
-
-#if _FOCUS_
-#if _PERC_STICKY_
-                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
-                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#else
-                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-                if (!e)
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
-                if (!to_evaluate.size())
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-#endif
-
-#if _TYPE_RSTEP_
-                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                {
-#if _TYPE_RSTEP_ == 1
-                    m_evaluator.randomize_local(to_evaluate);
-#elif _TYPE_RSTEP_ == 2
-                    mk_random_move(to_evaluate);
-#endif
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                }
-                continue;
-#endif
-
-#if _WEIGHT_DIST_ == 4
-                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif       
-                old_score = score;
-                new_const = (unsigned)-1;
-
-#if _VNS_
-                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    score = old_score;
-                    plateau_cnt++;
-#if _INTENSIFICATION_
-                    handle_plateau(g, score);
-                    //handle_plateau(g);
-                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-#if _PERC_PLATEAU_MOVES_
-                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
-                        mk_random_move(to_evaluate);
-                    else
-#endif
-#if _REPICK_
-                    m_evaluator.randomize_local(g, m_stats.m_moves);
-#else
-                    m_evaluator.randomize_local(to_evaluate);
-#endif
-#endif
-
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                } else {
-                    func_decl * fd = to_evaluate[new_const];              
-#if _REAL_RS_ || _REAL_PBFS_
-                    score = serious_score(g, fd, new_value);
-#else
-                    score = incremental_score(g, fd, new_value);    
-#endif
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        // main search loop
-        lbool search_old(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            
-            score = rescore(g);
-            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-                         tout << "Score distribution:"; 
-                         for (unsigned i = 0; i < g->size(); i++)
-                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                         tout << " TOP: " << score << std::endl; ); 
-        
-            unsigned plateau_cnt = 0;
-
-            // Andreas: Why do we only allow so few plateaus?
-#if _RESTARTS_
-            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
-            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
-#endif
-                do {
-                    checkpoint();
-
-#if _WEIGHT_DIST_ == 4
-                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-            
-#if _TYPE_RSTEP_
-                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                    {
-#if _TYPE_RSTEP_ == 1
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _TYPE_RSTEP_ == 2
-                        mk_random_move(g);
-#endif
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                            } else
-                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                        }
-                    }
-#endif
-                    old_score = score;
-                    new_const = (unsigned)-1;
-                        
-                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-                    if (!to_evaluate.size())
-                    {
-                        res = l_true;
-                        goto bailout;
-                    }
-                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
-                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
-                                                tout << to_evaluate[i]->get_name() << std::endl; );
-
-#if _VNS_
-                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-                    if (new_const == static_cast<unsigned>(-1)) {
-                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
-                                        for (unsigned i = 0; i < g->size(); i++) {
-                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
-                                        });
-
-                        TRACE("sls_max", m_tracker.show_model(tout);
-                                        tout << "Scores: " << std::endl;
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
-                                            m_tracker.get_score(g->form(i)) << std::endl; );
-                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
-                        score = old_score;
-                    }
-                    else {
-                        // Andreas: Why does randomizing not count as a move? (Now it does.)
-                        m_stats.m_moves++;
-                        func_decl * fd = to_evaluate[new_const];
-
-                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
-                                        switch (move) {
-                                        case MV_FLIP:  
-                                            tout << "Flip";
-                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
-                                            break;
-                                        case MV_INC: 
-                                            tout << "+1";
-                                            break;
-                                        case MV_DEC: 
-                                            tout << "-1";
-                                            break;
-                                        case MV_INV: 
-                                            tout << "NEG";
-                                            break;
-                                        };                                        
-                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
-
-                        switch (move) {
-                        case MV_FLIP: m_stats.m_flips++; break;
-                        case MV_INC: m_stats.m_incs++; break;
-                        case MV_DEC: m_stats.m_decs++; break;
-                        case MV_INV: m_stats.m_invs++; break;
-                        case MV_UMIN: m_stats.m_umins++; break;
-                        case MV_MUL2: m_stats.m_mul2s++; break;
-                        case MV_MUL3: m_stats.m_mul3s++; break;
-                        case MV_DIV2: m_stats.m_div2s++; break;
-                        }
-                    
-#if _REAL_RS_ || _REAL_PBFS_
-                        score = serious_score(g, fd, new_value);
-#else
-                        score = incremental_score(g, fd, new_value);    
-#endif
-
-                        TRACE("sls", tout << "Score distribution:"; 
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                                        tout << " TOP: " << score << std::endl; );                        
-                    }
-
-                    if (score >= 0.99999) {
-//                    if (score >= 1.0) {
-                        // score could theoretically be imprecise.
-                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
-                        bool all_true = true;
-                        for (unsigned i = 0; i < g->size() && all_true; i++)
-                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                all_true=false;
-                        if (all_true) {
-                            res = l_true; // sat
-                            goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                    /*
-                    if (m_stats.m_moves % 100 == 0)
-                    {
-                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-                    }*/
-                }
-                while (score > old_score && res == l_undef);                
-                
-                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
-                if (score != old_score) {
-                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
-                    plateau_cnt = 0;
-                } else {
-                    m_stats.m_moves++;
-                    plateau_cnt++;
-                    //report_tactic_progress("Plateau.", plateau_cnt);
-                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
-                    //if (plateau_cnt < m_plateau_limit) {
-                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
-#if _INTENSIFICATION_
-                        handle_plateau(g, score);
-                        //handle_plateau(g);
-#else
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#endif
-                        //mk_random_move(g);
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        void operator()(goal_ref const & g, model_converter_ref & mc) {
-            if (g->inconsistent()) {
-                mc = 0;
-                return;
-            }
-
-            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-            verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl;
-            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
-            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-            verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl;
-            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
-            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
-            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-            verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
-            verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
-            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
-            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-            
-#if _WEIGHT_DIST_ == 4
-            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-            m_tracker.initialize(g);
-            lbool res = l_undef;
-        
-            m_restart_limit = _RESTART_LIMIT_;
-
-            do {
-                checkpoint();
-
-                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                res = search(g);
-
-                if (res == l_undef)
-                {
-#if _RESTART_INIT_
-                    m_tracker.randomize(g);
-#else
-                    m_tracker.reset(g);
-#endif
-                }
-            }
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-        
-            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-            if (res == l_true) {    
-                report_tactic_progress("Number of flips:", m_stats.m_moves);
-                for (unsigned i = 0; i < g->size(); i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                    {
-                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                        NOT_IMPLEMENTED_YET(); 
-                    }
-
-                if (m_produce_models) {
-                    model_ref mdl = m_tracker.get_model();
-                    mc = model2model_converter(mdl.get());
-                    TRACE("sls_model", mc->display(tout); );
-                }
-                g->reset();
-            }
-            else
-                mc = 0;
-        }
-    };
-    
+class sls_tactic : public tactic {    
     ast_manager    & m;
     params_ref       m_params;
-    imp            * m_imp;
-    stats            m_stats;
+    sls_engine     * m_engine;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_imp = alloc(imp, m, p, m_stats);
+        m_engine = alloc(sls_engine, m, p);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -1395,16 +47,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_imp);
+        dealloc(m_engine);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_imp->updt_params(p);
+        m_engine->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        imp::collect_param_descrs(r);
+        sls_params::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -1412,14 +64,13 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());
-        m_imp->m_produce_models = g->models_enabled();        
+        SASSERT(g->is_well_sorted());        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_imp->operator()(g, mc);
+        m_engine->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -1428,40 +79,36 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = m_imp;
+        sls_engine * d = alloc(sls_engine, m, m_params);
         #pragma omp critical (tactic_cancel)
         {
-            d = m_imp;
+            std::swap(d, m_engine);
         }
         dealloc(d);
-        d = alloc(imp, m, m_params, m_stats);
-        #pragma omp critical (tactic_cancel) 
-        {
-            m_imp = d;
-        }
     }
     
     virtual void collect_statistics(statistics & st) const {
-        double seconds = m_stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", m_stats.m_restarts);
-        st.update("sls full evals", m_stats.m_full_evals);
-        st.update("sls incr evals", m_stats.m_incr_evals);
-        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
-        st.update("sls FLIP moves", m_stats.m_flips);    
-        st.update("sls INC moves", m_stats.m_incs);
-        st.update("sls DEC moves", m_stats.m_decs);
-        st.update("sls INV moves", m_stats.m_invs);
-        st.update("sls moves", m_stats.m_moves);
-        st.update("sls moves/sec", m_stats.m_moves / seconds);
+        sls_engine::stats const & stats = m_engine->get_stats();
+        double seconds = stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", stats.m_restarts);
+        st.update("sls full evals", stats.m_full_evals);
+        st.update("sls incr evals", stats.m_incr_evals);
+        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
+        st.update("sls FLIP moves", stats.m_flips);
+        st.update("sls INC moves", stats.m_incs);
+        st.update("sls DEC moves", stats.m_decs);
+        st.update("sls INV moves", stats.m_invs);
+        st.update("sls moves", stats.m_moves);
+        st.update("sls moves/sec", stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_stats.reset();
+        m_engine->reset_statistics();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_imp)
-            m_imp->set_cancel(f);
+        if (m_engine)
+            m_engine->set_cancel(f);
     }
 };
 

From 387f036f93287e912650b3738ef896d730b98152 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 19 Dec 2014 12:32:57 +0000
Subject: [PATCH 064/108] BV-SLS optimization

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 73355197a..89ef57871 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -89,6 +89,7 @@ private:
     unsigned              m_track_unsat;
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
+    obj_hashtable<expr>   m_temp_seen;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -440,6 +441,7 @@ public:
             }
         }
 
+        m_temp_seen.reset();
         for (unsigned i = 0; i < sz; i++)
         {
             expr * e = as[i];
@@ -630,7 +632,14 @@ public:
                 app * a = to_app(n);
                 expr * const * args = a->get_args();
                 for (unsigned i = 0; i < a->get_num_args(); i++)
-                    setup_occs(args[i]);
+                {
+                    expr * child = args[i];
+                    if (!m_temp_seen.contains(child))
+                    {
+                        setup_occs(child, false);
+                        m_temp_seen.insert(child);
+                    }
+                }
             }
             else if (m_manager.is_not(n))
             {
@@ -638,8 +647,7 @@ public:
                 app * a = to_app(n);
                 SASSERT(a->get_num_args() == 1);
                 expr * child = a->get_arg(0);
-                if (m_manager.is_and(child) || m_manager.is_or(child))
-                    NOT_IMPLEMENTED_YET();
+                SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child));
                 setup_occs(child, true);
             }
             else

From 6818e850e99faf6d6c63a44e5aadddeaa2e992a2 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 12 Jan 2015 15:59:20 +0000
Subject: [PATCH 065/108] Disabled BV-SLS as default tactic in anticipation for
 integration with the unstable branch.

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/portfolio/default_tactic.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 53da9a159..5a5cbcf94 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -32,8 +32,7 @@ Notes:
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
-  //                                      cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
+                                        cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),

From c982f870255edeed04c1e274fa0ff3213d358587 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 11 Feb 2014 17:44:59 +0000
Subject: [PATCH 066/108] sls tactic default

---
 src/tactic/portfolio/smt_strategic_solver.cpp | 5 +----
 1 file changed, 1 insertion(+), 4 deletions(-)

diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index f63b4fd8c..586c3a349 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -37,14 +37,11 @@ Notes:
 #include"horn_tactic.h"
 #include"smt_solver.h"
 
-#include"sls_tactic.h"
-
 tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
-   //     return mk_qfbv_tactic(m, p);
-        return mk_qfbv_sls_tactic(m, p);
+	    return mk_qfbv_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
     else if (logic=="QF_LIA")

From dfe2d945e94eb22b1e59958525a3ca0731f6aedb Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 18 Feb 2014 14:01:47 +0000
Subject: [PATCH 067/108] some extensions/modifications. versions added.

---
 src/tactic/portfolio/default_tactic.cpp |   2 +-
 src/tactic/sls/sls_evaluator.h          | 243 +--------
 src/tactic/sls/sls_tactic.cpp           | 661 ++++++++++++++++++++++--
 src/tactic/sls/sls_tracker.h            | 640 ++++++++---------------
 versions/z3-wsat-0.01.txt               |   4 +-
 versions/z3-wsat-0.01b.txt              |   4 +-
 6 files changed, 872 insertions(+), 682 deletions(-)

diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 5a5cbcf94..b28b7bec0 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -32,7 +32,7 @@ Notes:
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
+                                        cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 61afb7457..61305386e 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -20,8 +20,6 @@ Notes:
 #ifndef _SLS_EVALUATOR_H_
 #define _SLS_EVALUATOR_H_
 
-#include"model_evaluator.h"
-
 #include"sls_powers.h"
 #include"sls_tracker.h"
 
@@ -36,7 +34,6 @@ class sls_evaluator {
     powers              & m_powers;
     expr_ref_buffer       m_temp_exprs;
     vector<ptr_vector<expr> > m_traversal_stack;
-    vector<ptr_vector<expr> > m_traversal_stack_bool;
 
 public:
     sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : 
@@ -96,7 +93,7 @@ public:
                 SASSERT(n_args == 1);
                 const mpz & child = m_tracker.get_value(args[0]);
                 SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child));                
-                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);
+                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);                
                 break;
             }
             case OP_EQ: {
@@ -522,64 +519,11 @@ public:
         }    
     }
 
-    void run_serious_update(unsigned cur_depth) {
-        // precondition: m_traversal_stack contains the entry point(s)
-        expr_fast_mark1 visited;
-        mpz new_value;
-
-        double new_score;
-
-        SASSERT(cur_depth < m_traversal_stack.size());
-        while (cur_depth != static_cast<unsigned>(-1)) {
-            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
-
-            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
-                expr * cur = cur_depth_exprs[i];
-
-                (*this)(to_app(cur), new_value);
-                m_tracker.set_value(cur, new_value);
-
-                new_score = m_tracker.score(cur);
-                if (m_tracker.is_top_expr(cur))
-                {
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                    if (m_mpz_manager.eq(new_value,m_one))
-                        m_tracker.make_assertion(cur);
-                    else
-                        m_tracker.break_assertion(cur);
-                }
-
-                m_tracker.set_score(cur, new_score);
-                m_tracker.set_score_prune(cur, new_score);
-
-                if (m_tracker.has_uplinks(cur)) {
-                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                    for (unsigned j = 0; j < ups.size(); j++) {
-                        expr * next = ups[j];
-                        unsigned next_d = m_tracker.get_distance(next);
-                        SASSERT(next_d < cur_depth);
-                        if (!visited.is_marked(next)) {
-                            m_traversal_stack[next_d].push_back(next);
-                            visited.mark(next);
-                        }
-                    }
-                }
-            }
-
-            cur_depth_exprs.reset();
-            cur_depth--;
-        }
-
-        m_mpz_manager.del(new_value);
-    }
-
     void run_update(unsigned cur_depth) {
         // precondition: m_traversal_stack contains the entry point(s)
         expr_fast_mark1 visited;
         mpz new_value;
 
-        double new_score;
-
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -589,10 +533,8 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-                new_score = m_tracker.score(cur);
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score(cur, m_tracker.score(cur));
+
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -627,7 +569,8 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-        run_serious_update(max_depth);
+
+        run_update(max_depth);
     }
 
     void update(func_decl * fd, const mpz & new_value) {
@@ -641,174 +584,36 @@ public:
         run_update(cur_depth);
     }
 
-    void serious_update(func_decl * fd, const mpz & new_value) {
-        m_tracker.set_value(fd, new_value);
-        expr * ep = m_tracker.get_entry_point(fd);
-        unsigned cur_depth = m_tracker.get_distance(ep);
-        if (m_traversal_stack.size() <= cur_depth) 
-            m_traversal_stack.resize(cur_depth+1);
-        m_traversal_stack[cur_depth].push_back(ep);
+     void randomize_local(goal_ref const & g, unsigned int flip) {
+        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
 
-        run_serious_update(cur_depth);
-    }
+        // Randomize _all_ candidates:
 
-    unsigned run_update_bool_prune(unsigned cur_depth) {
-        expr_fast_mark1 visited;
+        //// bool did_something = false;
+        //for (unsigned i = 0; i < unsat_constants.size(); i++) {
+        //    func_decl * fd = unsat_constants[i];
+        //    mpz temp = m_tracker.get_random(fd->get_range());
+        //    // if (m_mpz_manager.neq(temp, m_tracker.get_value(fd))) {
+        //    //     did_something = true;
+        //    // }
+        //    update(fd, temp);
+        //    m_mpz_manager.del(temp);
+        //}
 
-        double prune_score, new_score;
-        unsigned pot_benefits = 0;
-        SASSERT(cur_depth < m_traversal_stack_bool.size());
- 
-        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-
-        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
-            expr * cur = cur_depth_exprs[i];
-
-            new_score = m_tracker.score(cur); 
-            if (m_tracker.is_top_expr(cur))
-                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-
-            prune_score = m_tracker.get_score_prune(cur);
-            m_tracker.set_score(cur, new_score);
-
-            if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
-                pot_benefits = 1;
-            if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
-                pot_benefits = 1;
-
-            if (m_tracker.has_uplinks(cur)) {
-                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                for (unsigned j = 0; j < ups.size(); j++) {
-                    expr * next = ups[j];
-                    unsigned next_d = m_tracker.get_distance(next);
-                    SASSERT(next_d < cur_depth);
-                    if (!visited.is_marked(next)) {
-                        m_traversal_stack_bool[next_d].push_back(next);
-                        visited.mark(next);
-                    }
-                }
-            }
-        }
-
-        cur_depth_exprs.reset();
-        cur_depth--;
- 
-        while (cur_depth != static_cast<unsigned>(-1)) {
-            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-            if (pot_benefits)
-            {
-                unsigned cur_size = cur_depth_exprs.size();
-                for (unsigned i = 0; i < cur_size; i++) {
-                    expr * cur = cur_depth_exprs[i];
-
-                    new_score = m_tracker.score(cur); 
-                    if (m_tracker.is_top_expr(cur))
-                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                    m_tracker.set_score(cur, new_score);
-
-                    if (m_tracker.has_uplinks(cur)) {
-                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                        for (unsigned j = 0; j < ups.size(); j++) {
-                            expr * next = ups[j];
-                            unsigned next_d = m_tracker.get_distance(next);
-                            SASSERT(next_d < cur_depth);
-                            if (!visited.is_marked(next)) {
-                                m_traversal_stack_bool[next_d].push_back(next);
-                                visited.mark(next);
-                            }
-                        }
-                    }
-                }
-            }
-            cur_depth_exprs.reset();
-            cur_depth--;
-        }
-
-        return pot_benefits;
-    }
-
-    void run_update_prune(unsigned max_depth) {
-        // precondition: m_traversal_stack contains the entry point(s)
-        expr_fast_mark1 visited;
-        mpz new_value;
-
-        unsigned cur_depth = max_depth;
-        SASSERT(cur_depth < m_traversal_stack.size());
-        while (cur_depth != static_cast<unsigned>(-1)) {
-            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
-
-            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
-                expr * cur = cur_depth_exprs[i];
-
-                (*this)(to_app(cur), new_value);
-                m_tracker.set_value(cur, new_value);
-                // Andreas: Should actually always have uplinks ...
-                if (m_tracker.has_uplinks(cur)) {
-                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                    for (unsigned j = 0; j < ups.size(); j++) {
-                        expr * next = ups[j];
-                        unsigned next_d = m_tracker.get_distance(next);
-                        SASSERT(next_d < cur_depth);
-                        if (!visited.is_marked(next)) {
-                            if (m_manager.is_bool(next))
-                                m_traversal_stack_bool[max_depth].push_back(next);
-                            else
-                                m_traversal_stack[next_d].push_back(next);
-                            visited.mark(next);
-                        }
-                    }
-                }
-            }
-
-            cur_depth_exprs.reset();
-            cur_depth--;
-        }
-
-        m_mpz_manager.del(new_value);
-    }
-
-    unsigned update_prune(func_decl * fd, const mpz & new_value) {
-        m_tracker.set_value(fd, new_value);
-        expr * ep = m_tracker.get_entry_point(fd);
-        unsigned cur_depth = m_tracker.get_distance(ep);
-
-        if (m_traversal_stack_bool.size() <= cur_depth)
-            m_traversal_stack_bool.resize(cur_depth+1);
-        if (m_traversal_stack.size() <= cur_depth) 
-                m_traversal_stack.resize(cur_depth+1);
-
-        if (m_manager.is_bool(ep))
-            m_traversal_stack_bool[cur_depth].push_back(ep);
-        else
-        {
-            m_traversal_stack[cur_depth].push_back(ep);
-            run_update_prune(cur_depth);
-        }
-        return run_update_bool_prune(cur_depth);
-    }
-
-    void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _one_ candidate:
         unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
         func_decl * fd = unsat_constants[r];
         mpz temp = m_tracker.get_random(fd->get_range());
-
-        serious_update(fd, temp);
-
+        update(fd, temp);
         m_mpz_manager.del(temp);
 
-        TRACE("sls",    tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
+        TRACE("sls", /*tout << "Randomization candidates: ";
+                        for (unsigned i = 0; i < unsat_constants.size(); i++)
+                            tout << unsat_constants[i]->get_name() << ", ";
+                        tout << std::endl;*/
+                        tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
                         tout << "Locally randomized model: " << std::endl; 
                         m_tracker.show_model(tout); );
-
-    }
-
-    void randomize_local(expr * e) {
-        randomize_local(m_tracker.get_constants(e));
-    } 
-
-    void randomize_local(ptr_vector<expr> const & as) {
-        randomize_local(m_tracker.get_unsat_constants(as));
     } 
 };
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 9bbed20bb..c194af267 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,30 +16,619 @@ Author:
 Notes:
 
 --*/
+#include<iomanip>
+#include"map.h"
 #include"nnf.h"
+#include"cooperate.h"
+#include"ast_smt2_pp.h"
+#include"ast_pp.h"
+#include"var_subst.h"
+#include"model_pp.h"
+#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"propagate_values_tactic.h"
-#include"ctx_simplify_tactic.h"
-#include"elim_uncnstr_tactic.h"
-#include"nnf_tactic.h"
 #include"stopwatch.h"
+#include"propagate_values_tactic.h"
 #include"sls_tactic.h"
-#include"sls_params.hpp"
-#include"sls_engine.h"
+#include"nnf_tactic.h"
 
-class sls_tactic : public tactic {    
+#define _CNF_ 0
+#define _BFS_ 1
+#define _FOCUS_ 1
+#define _RESTARTS_ 0
+#define _TIMELIMIT_ 30
+#define _SCORE_AND_AVG_ 0
+#define _SCORE_OR_MUL_ 0
+#define _VNS_ 0
+#define _WEIGHT_DIST_ 3
+#define _WEIGHT_DIST_FACTOR_ 0.1
+
+#include"sls_params.hpp"
+#include"sls_evaluator.h"
+#include"sls_tracker.h"
+
+class sls_tactic : public tactic {
+    class stats {
+    public:
+        unsigned        m_restarts;
+        stopwatch       m_stopwatch;    
+        unsigned        m_full_evals;
+        unsigned        m_incr_evals;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs;
+        stats() :
+            m_restarts(0),
+            m_full_evals(0),
+            m_incr_evals(0),
+            m_moves(0),
+            m_flips(0),
+            m_incs(0),
+            m_decs(0),
+            m_invs(0) {
+                m_stopwatch.reset();
+                m_stopwatch.start();
+            }
+        void reset() {
+            m_full_evals = m_flips = m_incr_evals = 0;
+            m_stopwatch.reset();
+            m_stopwatch.start();
+        }
+    };    
+
+    struct imp {       
+        ast_manager   & m_manager;
+        stats         & m_stats;
+        unsynch_mpz_manager m_mpz_manager;
+        powers          m_powers;
+        mpz             m_zero, m_one, m_two;            
+        bool            m_produce_models;
+        volatile bool   m_cancel;    
+        bv_util         m_bv_util;
+        sls_tracker     m_tracker;
+        sls_evaluator   m_evaluator;
+
+        unsigned        m_max_restarts;
+        unsigned        m_plateau_limit;
+
+        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;        
+
+        imp(ast_manager & m, params_ref const & p, stats & s) : 
+            m_manager(m),
+            m_stats(s),
+            m_powers(m_mpz_manager),
+            m_zero(m_mpz_manager.mk_z(0)),
+            m_one(m_mpz_manager.mk_z(1)),
+            m_two(m_mpz_manager.mk_z(2)),
+            m_cancel(false),
+            m_bv_util(m),
+            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
+            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
+        {
+            updt_params(p);
+        }
+
+        ~imp() {
+            m_mpz_manager.del(m_zero);
+            m_mpz_manager.del(m_one);
+            m_mpz_manager.del(m_two);
+        }        
+
+        ast_manager & m() const { return m_manager; }
+
+        void set_cancel(bool f) { m_cancel = f; }
+        void cancel() { set_cancel(true); }
+        void reset_cancel() { set_cancel(false); }
+
+        static void collect_param_descrs(param_descrs & r) {
+            sls_params::collect_param_descrs(r);
+        }
+
+        void updt_params(params_ref const & _p) {
+            sls_params p(_p);
+            m_produce_models = _p.get_bool("model", false);
+            m_max_restarts = p.restarts();            
+            m_tracker.set_random_seed(p.random_seed());
+            m_plateau_limit = p.plateau_limit();
+        }
+
+        void checkpoint() { 
+            if (m_cancel)
+                throw tactic_exception(TACTIC_CANCELED_MSG);
+            cooperate("sls");
+        }
+
+        bool full_eval(goal_ref const & g, model & mdl) {
+            bool res = true;
+
+            unsigned sz = g->size();
+            for (unsigned i = 0; i < sz && res; i++) {
+                checkpoint();
+                expr_ref o(m_manager);
+
+                if (!mdl.eval(g->form(i), o, true))
+                    exit(ERR_INTERNAL_FATAL);
+
+                res = m_manager.is_true(o.get());
+            }        
+
+            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
+
+            return res;
+        }
+
+        double top_score(goal_ref const & g) {
+            #if 0
+            double min = m_tracker.get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+                double q = m_tracker.get_score(g->form(i));
+                if (q < min) min = q;
+            }
+            TRACE("sls_top", tout << "Score distribution:"; 
+                                for (unsigned i = 0; i < sz; i++)
+                                    tout << " " << m_tracker.get_score(g->form(i));
+                                tout << " MIN: " << min << std::endl; );
+            return min;
+            #else
+            double top_sum = 0.0;
+            unsigned sz = g->size();
+            for (unsigned i = 0; i < sz; i++) {
+                top_sum += m_tracker.get_score(g->form(i));
+            }
+            TRACE("sls_top", tout << "Score distribution:"; 
+                                    for (unsigned i = 0; i < sz; i++)
+                                        tout << " " << m_tracker.get_score(g->form(i));
+                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
+            return top_sum / (double) sz;
+            #endif
+        }
+
+        double rescore(goal_ref const & g) {
+            m_evaluator.update_all();
+            m_stats.m_full_evals++;
+            return top_score(g);
+        }
+
+        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_evaluator.update(fd, new_value);
+            m_stats.m_incr_evals++;
+            return top_score(g);
+        }
+
+        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+        
+            #ifdef Z3DEBUG
+            mpz old_value;
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+            #endif
+
+            double r = incremental_score(g, fd, temp);
+        
+            #ifdef Z3DEBUG
+            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
+                                        " --> " << r << std::endl; );
+        
+            m_mpz_manager.del(old_value);
+            #endif
+
+            if (r >= best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+            unsigned shift;        
+            m_mpz_manager.add(old_value, m_one, incremented);
+            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
+                m_mpz_manager.set(incremented, m_zero);
+        }
+
+        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
+            if (m_mpz_manager.is_zero(old_value)) {
+                m_mpz_manager.set(decremented, m_powers(bv_sz));
+                m_mpz_manager.dec(decremented);
+            }
+            else
+                m_mpz_manager.sub(old_value, m_one, decremented);
+        }
+
+        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
+            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
+        }
+
+        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
+            m_mpz_manager.set(flipped, m_zero);
+
+            if (m_bv_util.is_bv_sort(s)) {
+                mpz mask;
+                m_mpz_manager.set(mask, m_powers(bit));
+                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
+                m_mpz_manager.del(mask);
+            }
+            else if (m_manager.is_bool(s))
+                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
+            else
+                NOT_IMPLEMENTED_YET();
+        }
+
+        void mk_random_move(goal_ref const & g) {
+            unsigned rnd_mv = 0;
+            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+            move_type mt = (move_type) rnd_mv;
+
+            // inversion doesn't make sense, let's do a flip instead.
+            if (mt == MV_INV) mt = MV_FLIP;
+
+			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
+            unsigned ucc = unsat_constants.size(); 
+            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
+            func_decl * fd = unsat_constants[rc];
+            mpz new_value;
+            unsigned bit = 0;
+
+            switch (mt)
+            {
+            case MV_FLIP: {
+                unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range());
+                bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+                mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+                break;
+            }
+            case MV_INC: 
+                mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                break;
+            case MV_DEC: 
+                mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                break;
+            case MV_INV:
+                mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                break;
+            default:
+                NOT_IMPLEMENTED_YET();
+            }
+
+            m_evaluator.update(fd, new_value);            
+
+            TRACE("sls", tout << "Randomization candidates: ";
+                         for (unsigned i = 0; i < unsat_constants.size(); i++)
+                             tout << unsat_constants[i]->get_name() << ", ";
+                         tout << std::endl;
+                         tout << "Random move: ";
+                         switch (mt) {
+                         case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+                         case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+                         case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+                         case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+                         }
+                         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+
+            m_mpz_manager.del(new_value);
+        }
+
+        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz, max_bv_sz = 0;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+				if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+
+					// try to flip lsb
+					mk_flip(srt, old_value, 0, temp);                
+	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+	                    new_bit = 0;
+	                    move = MV_FLIP;
+					}
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+
+#if _VNS_ == 1
+			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+			if (new_score <= score)
+			for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+				if (j < bv_sz)
+				{
+					mk_flip(srt, old_value, j, temp);                
+
+	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+	                    new_bit = j;
+	                    move = MV_FLIP;
+	                }
+				}
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+			m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
+        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
+        lbool search(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            
+            score = rescore(g);
+            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+                         tout << "Score distribution:"; 
+                         for (unsigned i = 0; i < g->size(); i++)
+                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                         tout << " TOP: " << score << std::endl; ); 
+        
+            unsigned plateau_cnt = 0;
+
+			// Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
+                do {
+                    checkpoint();
+            
+                    old_score = score;
+                    new_const = (unsigned)-1;
+                        
+					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+
+                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
+                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
+                                                tout << to_evaluate[i]->get_name() << std::endl; );
+
+#if _VNS_
+                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+                    if (new_const == static_cast<unsigned>(-1)) {
+                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
+                                        for (unsigned i = 0; i < g->size(); i++) {
+                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                                        });
+
+                        TRACE("sls_max", m_tracker.show_model(tout);
+                                        tout << "Scores: " << std::endl;
+                                        for (unsigned i = 0; i < g->size(); i++)
+                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
+                                            m_tracker.get_score(g->form(i)) << std::endl; );
+						// Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                        score = old_score;
+                    }
+                    else {
+						// Andreas: Why does randomizing not count as a move? (Now it does.)
+                        m_stats.m_moves++;
+                        func_decl * fd = to_evaluate[new_const];
+
+                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
+                                        switch (move) {
+                                        case MV_FLIP:  
+                                            tout << "Flip";
+                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
+                                            break;
+                                        case MV_INC: 
+                                            tout << "+1";
+                                            break;
+                                        case MV_DEC: 
+                                            tout << "-1";
+                                            break;
+                                        case MV_INV: 
+                                            tout << "NEG";
+                                            break;
+                                        };                                        
+                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
+
+                        switch (move) {
+                        case MV_FLIP: m_stats.m_flips++; break;
+                        case MV_INC: m_stats.m_incs++; break;
+                        case MV_DEC: m_stats.m_decs++; break;
+                        case MV_INV: m_stats.m_invs++; break;
+                        }
+                    
+                        score = incremental_score(g, fd, new_value);    
+
+                        TRACE("sls", tout << "Score distribution:"; 
+                                        for (unsigned i = 0; i < g->size(); i++)
+                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                                        tout << " TOP: " << score << std::endl; );                        
+                    }
+
+                    if (score >= 1.0) {
+                        // score could theoretically be imprecise.
+						// Andreas: Can it only be imprecise in one direction?
+                        bool all_true = true;
+                        for (unsigned i = 0; i < g->size() && all_true; i++)
+                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                all_true=false;
+                        if (all_true) {
+                            res = l_true; // sat
+                            goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
+					/*
+					if (m_stats.m_moves % 100 == 0)
+					{
+						verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+						verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+					}*/
+                }
+                while (score > old_score && res == l_undef);                
+				
+				// Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                if (score != old_score) {
+					report_tactic_progress("This should not happen I guess.", plateau_cnt);
+                    plateau_cnt = 0;
+				} else {
+					m_stats.m_moves++;
+                    plateau_cnt++;
+					//report_tactic_progress("Plateau.", plateau_cnt);
+					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //if (plateau_cnt < m_plateau_limit) {
+                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
+						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        //mk_random_move(g);
+                        score = top_score(g);
+                    //}
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        void operator()(goal_ref const & g, model_converter_ref & mc) {
+            if (g->inconsistent()) {
+                mc = 0;
+                return;
+            }
+
+            m_tracker.initialize(g);
+            lbool res = l_undef;
+        
+            do {
+                checkpoint();
+				// Andreas: I think restarts are too impotant to ignore 99% of them are happening...
+                //if ((m_stats.m_restarts % 100) == 0)                        
+                    report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+                
+                res = search(g);
+
+                if (res == l_undef)
+                    m_tracker.randomize();
+            }
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+        
+			verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+
+            if (res == l_true) {    
+				report_tactic_progress("Number of flips:", m_stats.m_moves);
+                if (m_produce_models) {
+                    model_ref mdl = m_tracker.get_model();
+                    mc = model2model_converter(mdl.get());
+                    TRACE("sls_model", mc->display(tout); );
+                }
+                g->reset();
+            }
+            else
+                mc = 0;
+        }
+    };
+    
     ast_manager    & m;
     params_ref       m_params;
-    sls_engine     * m_engine;
+    imp            * m_imp;
+    stats            m_stats;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_engine = alloc(sls_engine, m, p);
+        m_imp = alloc(imp, m, p, m_stats);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -47,16 +636,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_engine);
+        dealloc(m_imp);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_engine->updt_params(p);
+        m_imp->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        sls_params::collect_param_descrs(r);
+        imp::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -64,13 +653,14 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());        
+        SASSERT(g->is_well_sorted());
+        m_imp->m_produce_models = g->models_enabled();        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_engine->operator()(g, mc);
+        m_imp->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -79,36 +669,35 @@ public:
     }
 
     virtual void cleanup() {        
-        sls_engine * d = alloc(sls_engine, m, m_params);
+        imp * d = alloc(imp, m, m_params, m_stats);
         #pragma omp critical (tactic_cancel)
         {
-            std::swap(d, m_engine);
+            std::swap(d, m_imp);
         }
         dealloc(d);
     }
     
     virtual void collect_statistics(statistics & st) const {
-        sls_engine::stats const & stats = m_engine->get_stats();
-        double seconds = stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", stats.m_restarts);
-        st.update("sls full evals", stats.m_full_evals);
-        st.update("sls incr evals", stats.m_incr_evals);
-        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
-        st.update("sls FLIP moves", stats.m_flips);
-        st.update("sls INC moves", stats.m_incs);
-        st.update("sls DEC moves", stats.m_decs);
-        st.update("sls INV moves", stats.m_invs);
-        st.update("sls moves", stats.m_moves);
-        st.update("sls moves/sec", stats.m_moves / seconds);
+        double seconds = m_stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", m_stats.m_restarts);
+        st.update("sls full evals", m_stats.m_full_evals);
+        st.update("sls incr evals", m_stats.m_incr_evals);
+        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
+        st.update("sls FLIP moves", m_stats.m_flips);    
+        st.update("sls INC moves", m_stats.m_incs);
+        st.update("sls DEC moves", m_stats.m_decs);
+        st.update("sls INV moves", m_stats.m_invs);
+        st.update("sls moves", m_stats.m_moves);
+        st.update("sls moves/sec", m_stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_engine->reset_statistics();
+        m_stats.reset();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_engine)
-            m_engine->set_cancel(f);
+        if (m_imp)
+            m_imp->set_cancel(f);
     }
 };
 
@@ -143,9 +732,6 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
     // conservative gaussian elimination. 
     gaussian_p.set_uint("gaussian_max_occs", 2); 
 
-    params_ref ctx_p;
-    ctx_p.set_uint("max_depth", 32);
-    ctx_p.set_uint("max_steps", 5000000);
     return and_then(and_then(mk_simplify_tactic(m),                             
                              mk_propagate_values_tactic(m),
                              using_params(mk_solve_eqs_tactic(m), gaussian_p),
@@ -154,12 +740,17 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
+#if _CNF_
+						// Andreas: We will probably never use this. CNF sucks.
+                        mk_cnf_tactic(m, p));
+#else
+						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
+#endif
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
     tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
-    //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 89ef57871..1061bd90e 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,14 +20,6 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"for_each_expr.h"
-#include"ast_smt2_pp.h"
-#include"bv_decl_plugin.h"
-#include"model.h"
-
-#include"sls_params.hpp"
-#include"sls_powers.h"
-
 class sls_tracker {
     ast_manager         & m_manager;
     unsynch_mpz_manager & m_mpz_manager;
@@ -36,26 +28,21 @@ class sls_tracker {
     random_gen            m_rng;
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
-    mpz                   m_zero, m_one, m_two;
-        
+    mpz                   m_zero, m_one, m_two;   
+	    
     struct value_score { 
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { };
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
-        double score_prune;
-        unsigned has_pos_occ;
-        unsigned has_neg_occ;
         unsigned distance; // max distance from any root
-        unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
-            touched = other.touched;
             return *this;
         }
     };
@@ -67,29 +54,12 @@ private:
     typedef obj_map<expr, value_score> scores_type;    
     typedef obj_map<expr, ptr_vector<expr> > uplinks_type;    
     typedef obj_map<expr, ptr_vector<func_decl> > occ_type;
-    obj_hashtable<expr>	  m_top_expr;
     scores_type           m_scores;
     uplinks_type          m_uplinks;
     entry_point_type      m_entry_points;
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
-    unsigned              m_last_pos;
-    unsigned              m_walksat;
-    unsigned              m_ucb;
-    double                m_ucb_constant;
-    unsigned              m_ucb_init;
-    double                m_ucb_forget;
-    double                m_ucb_noise;
-    unsigned              m_touched;
-    double                m_scale_unsat;
-    unsigned              m_paws_init;
-    obj_map<expr, unsigned>	m_where_false;
-    expr**					m_list_false;
-    unsigned              m_track_unsat;
-    obj_map<expr, unsigned> m_weights;
-    double				  m_top_sum;
-    obj_hashtable<expr>   m_temp_seen;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -109,59 +79,6 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
-    void updt_params(params_ref const & _p) {
-        sls_params p(_p);
-        m_walksat = p.walksat();
-        m_ucb = p.walksat_ucb();
-        m_ucb_constant = p.walksat_ucb_constant();
-        m_ucb_init = p.walksat_ucb_init();
-        m_ucb_forget = p.walksat_ucb_forget();
-        m_ucb_noise = p.walksat_ucb_noise();
-        m_scale_unsat = p.scale_unsat();
-        m_paws_init = p.paws_init();
-        // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy.
-        // If you want to use it, you will also need to change comments in the assertion selection.
-        m_track_unsat = 0;//p.track_unsat();
-    }
-
-    /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently.
-    unsigned get_formula_size() {
-        return m_scores.size();
-    }
-
-    double get_avg_bw(goal_ref const & g) {
-        double sum = 0.0;
-        unsigned count = 0;
-
-        for (unsigned i = 0; i < g->size(); i++)
-        {
-            m_temp_constants.reset();
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(g->form(i));
-            unsigned sz = this_decls.size();
-            for (unsigned i = 0; i < sz; i++) {
-                func_decl * fd = this_decls[i];
-                m_temp_constants.push_back(fd);
-                sort * srt = fd->get_range();
-                sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);         
-                count++;
-            }
-        }
-
-        return sum / count;   
-    }*/
-
-    inline void adapt_top_sum(expr * e, double add, double sub) {
-        m_top_sum += m_weights.find(e) * (add - sub);
-    }
-
-    inline void set_top_sum(double new_score) {
-        m_top_sum = new_score;
-    }
-
-    inline double get_top_sum() {
-        return m_top_sum;
-    }
-
     inline void set_value(expr * n, const mpz & r) {
         SASSERT(m_scores.contains(n));
         m_mpz_manager.set(m_scores.find(n).value, r);
@@ -206,26 +123,6 @@ public:
         return get_score(ep);
     }
 
-    inline void set_score_prune(expr * n, double score) {
-        SASSERT(m_scores.contains(n));
-        m_scores.find(n).score_prune = score;
-    }
-
-    inline double & get_score_prune(expr * n) {
-        SASSERT(m_scores.contains(n));
-        return m_scores.find(n).score_prune;
-    }
-
-    inline unsigned has_pos_occ(expr * n) {
-        SASSERT(m_scores.contains(n));
-        return m_scores.find(n).has_pos_occ;
-    }
-
-    inline unsigned has_neg_occ(expr * n) {
-        SASSERT(m_scores.contains(n));
-        return m_scores.find(n).has_neg_occ;
-    }
-
     inline unsigned get_distance(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).distance;
@@ -249,32 +146,11 @@ public:
         return m_uplinks.contains(n);
     }
 
-    inline bool is_top_expr(expr * n) {
-        return m_top_expr.contains(n);
-    }
-
     inline ptr_vector<expr> & get_uplinks(expr * n) {
         SASSERT(m_uplinks.contains(n));
         return m_uplinks.find(n);
     }
 
-    inline void ucb_forget(ptr_vector<expr> & as) {
-        if (m_ucb_forget < 1.0)
-        {
-            expr * e;
-            unsigned touched_old, touched_new;
-
-            for (unsigned i = 0; i < as.size(); i++)
-            {
-                e = as[i];
-                touched_old = m_scores.find(e).touched;
-                touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1);
-                m_scores.find(e).touched = touched_new;
-                m_touched += touched_new - touched_old;
-            }
-        }
-    }
-
     void initialize(app * n) {
         // Build score table
         if (!m_scores.contains(n)) {
@@ -350,12 +226,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(ptr_vector<expr> const & as) {
+    void calculate_expr_distances(goal_ref const & g) {
         // precondition: m_scores is set up.
-        unsigned sz = as.size();
+        unsigned sz = g->size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(as[i]));
+            stack.push_back(to_app(g->form(i)));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -373,53 +249,57 @@ public:
         }
     }
 
-    /* Andreas: Used this at some point to have values for the non-top-level expressions.
-                However, it did not give better performance but even cause some additional m/o - is not used currently.
-    void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
-        if (m_manager.is_and(e) || m_manager.is_or(e)) {
-            app * a = to_app(e);
-            expr * const * args = a->get_args();
-            unsigned int sz = a->get_num_args();
-            for (unsigned int i = 0; i < sz; i++) {
-                expr * q = args[i];
-                initialize_recursive(proc, visited, q);
-            }
-        }
-        for_each_expr(proc, visited, e);
-    }
+	void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
+		if (m_manager.is_and(e) || m_manager.is_or(e)) {
+			app * a = to_app(e);
+			expr * const * args = a->get_args();
+			unsigned int sz = a->get_num_args();
+			for (unsigned int i = 0; i < sz; i++) {
+		        expr * q = args[i];
+				initialize_recursive(proc, visited, q);
+			}
+		}
+		for_each_expr(proc, visited, e);
+ 	}
 
-    void initialize_recursive(expr * e) {
-        if (m_manager.is_and(e) || m_manager.is_or(e)) {
-            app * a = to_app(e);
-            expr * const * args = a->get_args();
-            unsigned int sz = a->get_num_args();
-            for (unsigned int i = 0; i < sz; i++) {
-                expr * q = args[i];
-                initialize_recursive(q);
-            }
-        }
-        ptr_vector<func_decl> t;
+	void initialize_recursive(expr * e) {
+		if (m_manager.is_and(e) || m_manager.is_or(e)) {
+			app * a = to_app(e);
+			expr * const * args = a->get_args();
+			unsigned int sz = a->get_num_args();
+			for (unsigned int i = 0; i < sz; i++) {
+		        expr * q = args[i];
+				initialize_recursive(q);
+			}
+		}
+		ptr_vector<func_decl> t;
         m_constants_occ.insert_if_not_there(e, t);
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
-    }*/
+ 	}
 
-    void initialize(ptr_vector<expr> const & as) {
+	void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = as.size();
+        unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = as[i];
-            if (!m_top_expr.contains(e))
-                m_top_expr.insert(e);
+            expr * e = g->form(i);
+			// Andreas: Maybe not fully correct.
+#if _FOCUS_ == 2
+			initialize_recursive(proc, visited, e);
+#endif
             for_each_expr(proc, visited, e);
         }
 
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = as[i];
+            expr * e = g->form(i);
+			// Andreas: Maybe not fully correct.
+#if _FOCUS_ == 2
+			initialize_recursive(e);
+#endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -427,82 +307,9 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(as);
+        calculate_expr_distances(g);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
-
-        if (m_track_unsat)
-        {
-            m_list_false = new expr*[sz];
-            for (unsigned i = 0; i < sz; i++)
-            {
-        	    if (m_mpz_manager.eq(get_value(as[i]), m_zero))
-                    break_assertion(as[i]);
-            }
-        }
-
-        m_temp_seen.reset();
-        for (unsigned i = 0; i < sz; i++)
-        {
-            expr * e = as[i];
-
-            // initialize weights
-            if (!m_weights.contains(e))
-        		m_weights.insert(e, m_paws_init);
-
-            // positive/negative occurences used for early pruning
-            setup_occs(as[i]);
-        }
-
-        // initialize ucb total touched value (individual ones are always initialized to 1)
-        m_touched = m_ucb_init ? as.size() : 1;
-    }
-
-    void increase_weight(expr * e)
-    {
-        m_weights.find(e)++;
-    }
-
-    void decrease_weight(expr * e)
-    {
-        unsigned old_weight = m_weights.find(e);
-        m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init;
-    }
-
-    unsigned get_weight(expr * e)
-    {
-        return m_weights.find(e);
-    }
-
-    void make_assertion(expr * e)
-    {
-        if (m_track_unsat)
-        {
-            if (m_where_false.contains(e))
-            {
-                unsigned pos = m_where_false.find(e);
-                m_where_false.erase(e);
-                if (pos != m_where_false.size())
-                {
-                    expr * q = m_list_false[m_where_false.size()];
-                    m_list_false[pos] = q;
-                    m_where_false.find(q) = pos;
-                }
-            }
-        }
-    }
-
-    void break_assertion(expr * e)
-    {
-        if (m_track_unsat)
-        {
-            if (!m_where_false.contains(e))
-            {
-                unsigned pos = m_where_false.size();
-                m_list_false[pos] = e;
-                m_where_false.insert(e, pos);
-            }
-        }
     }
 
     void show_model(std::ostream & out) {
@@ -599,7 +406,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(ptr_vector<expr> const & as) {
+    void randomize() {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -613,55 +420,6 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
     }              
 
-    void reset(ptr_vector<expr> const & as) {
-        TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
-
-        for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
-            mpz temp = m_zero;
-            set_value(it->m_value, temp);
-            m_mpz_manager.del(temp);
-        }
-    }              
-
-    void setup_occs(expr * n, bool negated = false) {
-        if (m_manager.is_bool(n))
-        {
-            if (m_manager.is_and(n) || m_manager.is_or(n))
-            {
-                SASSERT(!negated);
-                app * a = to_app(n);
-                expr * const * args = a->get_args();
-                for (unsigned i = 0; i < a->get_num_args(); i++)
-                {
-                    expr * child = args[i];
-                    if (!m_temp_seen.contains(child))
-                    {
-                        setup_occs(child, false);
-                        m_temp_seen.insert(child);
-                    }
-                }
-            }
-            else if (m_manager.is_not(n))
-            {
-                SASSERT(!negated);
-                app * a = to_app(n);
-                SASSERT(a->get_num_args() == 1);
-                expr * child = a->get_arg(0);
-                SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child));
-                setup_occs(child, true);
-            }
-            else
-            {
-                if (negated)
-                    m_scores.find(n).has_neg_occ = 1;
-                else
-                    m_scores.find(n).has_pos_occ = 1;
-            }
-        }
-        else
-            NOT_IMPLEMENTED_YET();
-    }
-
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
@@ -678,28 +436,41 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            /* Andreas: Seems to have no effect. But maybe you want to try it again at some point.
+			// Andreas: Seems to have no effect. Probably it does not even occur.
+#if _SCORE_AND_AVG_
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
                 sum += get_score(args[i]);
-            res = sum / (double) a->get_num_args(); */
-            double min = 1.0;
+            res = sum / (double) a->get_num_args();
+#else
+			double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur < min) min = cur;
             }
             res = min;
+#endif
         }
         else if (m_manager.is_or(n)) {
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            double max = 0.0;
+			// Andreas: Seems to have no effect. Probably it is still too similar to the original version.
+#if _SCORE_OR_MUL_
+			double inv = 1.0;
+            for (unsigned i = 0; i < a->get_num_args(); i++) {
+                double cur = get_score(args[i]);
+                inv *= (1.0 - get_score(args[i]));
+            }
+            res = 1.0 - inv;
+#else
+			double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur > max) max = cur;
             }
             res = max;
+#endif
         }
         else if (m_manager.is_ite(n)) {
             SASSERT(!negated);
@@ -717,7 +488,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-            
+
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -733,14 +504,24 @@ public:
                 m_mpz_manager.bitwise_xor(v0, v1, diff);
                 unsigned hamming_distance = 0;
                 unsigned bv_sz = m_bv_util.get_bv_size(arg0);
-                // unweighted hamming distance
+                #if 1 // unweighted hamming distance
                 while (!m_mpz_manager.is_zero(diff)) {
+                    //m_mpz_manager.set(diff_m1, diff);
+                    //m_mpz_manager.dec(diff_m1);
+                    //m_mpz_manager.bitwise_and(diff, diff_m1, diff);
+                    //hamming_distance++;
                     if (!m_mpz_manager.is_even(diff)) {
                         hamming_distance++;
                     }
                     m_mpz_manager.machine_div(diff, m_two, diff);
                 }
                 res = 1.0 - (hamming_distance / (double) bv_sz);
+                #else                    
+                rational r(diff);
+                r /= m_powers(bv_sz);
+                double dbl = r.get_double();
+                res = (dbl < 0.0) ? 1.0 : (dbl > 1.0) ? 0.0 : 1.0 - dbl;
+                #endif
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << " ; HD = " << hamming_distance << 
                                         " ; SZ = " << bv_sz << std::endl; );                    
@@ -755,7 +536,7 @@ public:
             SASSERT(a->get_num_args() == 2);
             const mpz & x = get_value(a->get_arg(0));
             const mpz & y = get_value(a->get_arg(1));
-            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
+            unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
 
             if (negated) {
                 if (m_mpz_manager.gt(x, y))
@@ -769,7 +550,7 @@ public:
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
                     res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-                    m_mpz_manager.del(diff);
+					m_mpz_manager.del(diff);
                 }
             }
             else {
@@ -781,7 +562,7 @@ public:
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));
                     double dbl = n.get_double();
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
                 }
             }
@@ -801,7 +582,7 @@ public:
 
             if (negated) {
                 if (x > y)
-                    res = 1.0; 
+                    res = 1.0;
                 else {
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
@@ -817,21 +598,20 @@ public:
             }
             else {
                 if (x <= y)
-                    res = 1.0; 
+                    res = 1.0;
                 else {
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
-                    SASSERT(!m_mpz_manager.is_neg(diff));
                     rational n(diff);
                     n /= p;
                     double dbl = n.get_double();
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
-            m_mpz_manager.del(x);
+			m_mpz_manager.del(x);
             m_mpz_manager.del(y);                
         }
         else if (m_manager.is_not(n)) {                
@@ -839,9 +619,7 @@ public:
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 1);
             expr * child = a->get_arg(0);
-            // Precondition: Assertion set is in NNF.
-            // Also: careful about the unsat assertion scaling further down.
-            if (m_manager.is_and(child) || m_manager.is_or(child)) 
+            if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
                 NOT_IMPLEMENTED_YET();
             res = score_bool(child, true);
         }
@@ -867,16 +645,24 @@ public:
 
         SASSERT(res >= 0.0 && res <= 1.0);
 
-        app * a = to_app(n);
-        family_id afid = a->get_family_id();
+#if _WEIGHT_DIST_
+		app * a = to_app(n);
+		family_id afid = a->get_family_id();
+		if (afid == m_bv_util.get_family_id())
+#endif
+#if _WEIGHT_DIST_ == 1
+		if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+#elif _WEIGHT_DIST_ == 2
+		res *= res;
+#elif _WEIGHT_DIST_ == 3
+		if (res < 1.0) res = 0.0;
+#endif
 
-        if (afid == m_bv_util.get_family_id())
-            if (res < 1.0) res *= m_scale_unsat;
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-    
+
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -922,28 +708,9 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-    ptr_vector<func_decl> & get_constants(expr * e) {
-        ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
-        unsigned sz = this_decls.size();
+	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
-            func_decl * fd = this_decls[i];
-            if (!m_temp_constants.contains(fd))
-                m_temp_constants.push_back(fd);
-        }
-        return m_temp_constants;
-    }
-
-    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as) {
-        unsigned sz = as.size();
-        if (sz == 1) {
-            if (m_mpz_manager.neq(get_value(as[0]), m_one))
-                return get_constants();
-        }
-
-        m_temp_constants.reset();
-
-        for (unsigned i = 0; i < sz; i++) {
-            expr * q = as[i];
+            expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -955,110 +722,141 @@ public:
             }
         }
         return m_temp_constants;
-    }
+	}
 
-    ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
-            if (!e || m_temp_constants.size())
-                return m_temp_constants;
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
-            unsigned sz = this_decls.size();
-            for (unsigned j = 0; j < sz; j++) {
+	expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+			for (unsigned i = pos; i < sz; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+		            return q;
+			}
+			for (unsigned i = 0; i < pos; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+		            return q;
+            }
+			return 0;
+	}
+
+	ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+			expr * q = get_unsat_assertion(g, sz, pos);
+            // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
+			if (!q)
+				return m_temp_constants;
+
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-            return m_temp_constants;
-    }
+	        return m_temp_constants;
+	}
 
-    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as) {
-        if (m_walksat)
-        {
-            expr * e = get_unsat_assertion(as);
-
-            if (!e)
-            {
-                m_temp_constants.reset();
-                return m_temp_constants;
+	ptr_vector<func_decl> & go_deeper(expr * e) {
+			if (m_manager.is_bool(e)) {
+				if (m_manager.is_and(e)) {
+					app * a = to_app(e);
+					expr * const * args = a->get_args();
+				    // Andreas: might be used for guided branching
+					//for (unsigned i = 0; i < a->get_num_args(); i++) {
+						//double cur = get_score(args[i]);
+					//}
+					// Andreas: A random number is better here since reusing flip will cause patterns.
+					unsigned int sz = a->get_num_args();
+					unsigned int pos = get_random_uint(16) % sz;
+					for (unsigned int i = pos; i < sz; i++) {
+		                expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+					}
+					for (unsigned int i = 0; i < pos; i++) {
+						expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+		            }
+		        }
+				else if (m_manager.is_or(e)) {
+					app * a = to_app(e);
+					expr * const * args = a->get_args();
+					unsigned int sz = a->get_num_args();
+					unsigned int pos = get_random_uint(16) % sz;
+					for (unsigned int i = pos; i < sz; i++) {
+		                expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+					}
+					for (unsigned int i = 0; i < pos; i++) {
+						expr * q = args[i];
+		                if (m_mpz_manager.neq(get_value(q), m_one))
+				            return go_deeper(q);
+		            }
+		        }
+			}
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
             }
+	        return m_temp_constants;
+	}
+
+	ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+		expr * q = get_unsat_assertion(g, sz, pos);
+        if (!q)
+			return m_temp_constants;
+
+		return go_deeper(q);
+	}
+
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
 
-            return get_unsat_constants_walksat(e);
-        }
-        else
-            return get_unsat_constants_gsat(as);
-    }
-    
-    expr * get_unsat_assertion(ptr_vector<expr> const & as) {
-        unsigned sz = as.size();
         if (sz == 1) {
-            if (m_mpz_manager.neq(get_value(as[0]), m_one))
-                return as[0];
-            else
-                return 0;
+            return get_constants();
         }
-        m_temp_constants.reset();
-
-        unsigned pos = -1;
-        if (m_ucb)
-        {
-            value_score vscore;
-            double max = -1.0;
-            // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit.
-            /* for (unsigned i = 0; i < m_where_false.size(); i++) {
-                expr * e = m_list_false[i]; */
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = as[i];
-                if (m_mpz_manager.neq(get_value(e), m_one))
-                {
-                    vscore = m_scores.find(e);
-                    // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise.
-                    // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
-                    double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); 
-                    if (q > max) { max = q; pos = i; }
-                }
+        else {
+            m_temp_constants.reset();
+#if _FOCUS_ == 1
+#if _BFS_ == 3
+			unsigned int pos = 0;
+			double max = get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+				expr * e = g->form(i);
+                double q = get_score(e);
+				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-            if (pos == static_cast<unsigned>(-1))
-                return 0;
-
-            m_touched++;
-            m_scores.find(as[pos]).touched++;
-            // Andreas: Also part of track_unsat data structures. Additionally disable the previous line!
-            /* m_last_pos = pos;
-            m_scores.find(m_list_false[pos]).touched++;
-            return m_list_false[pos]; */
+#elif _BFS_ == 2
+			unsigned int pos = 0;
+			double min = get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+				expr * e = g->form(i);
+                double q = get_score(e);
+				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+            }
+#elif _BFS_ == 1
+			unsigned int pos = flip % m_constants.size();
+#else
+			unsigned int pos = get_random_uint(16) % m_constants.size();
+#endif
+			return get_unsat_constants_walksat(g, sz, pos);
+#elif _FOCUS_ == 2
+#if _BFS_
+			unsigned int pos = flip % m_constants.size();
+#else
+			unsigned int pos = get_random_uint(16) % m_constants.size();
+#endif
+			return get_unsat_constants_crsat(g, sz, pos);
+#else
+			return get_unsat_constants_gsat(g, sz);
+#endif
         }
-        else
-        {
-            // Andreas: The track_unsat data structures for random assertion selection.
-            /* sz = m_where_false.size();
-            if (sz == 0)
-                return 0;
-            return m_list_false[get_random_uint(16) % sz]; */
-
-            unsigned cnt_unsat = 0;
-            for (unsigned i = 0; i < sz; i++)
-                if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-            if (pos == static_cast<unsigned>(-1))
-                return 0;
-        }
-        
-        m_last_pos = pos;
-        return as[pos];
-    }
-
-    expr * get_new_unsat_assertion(ptr_vector<expr> const & as) {
-        unsigned sz = as.size();
-        if (sz == 1)
-            return 0;
-        m_temp_constants.reset();
-        
-        unsigned cnt_unsat = 0, pos = -1;
-        for (unsigned i = 0; i < sz; i++)
-            if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
-        return as[pos];
     }
 };
 
-#endif
+#endif
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt
index fec38518d..141193f76 100644
--- a/versions/z3-wsat-0.01.txt
+++ b/versions/z3-wsat-0.01.txt
@@ -9,6 +9,4 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
-
-BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt
index 8bcf2ffeb..2c0c0e7ad 100644
--- a/versions/z3-wsat-0.01b.txt
+++ b/versions/z3-wsat-0.01b.txt
@@ -9,6 +9,4 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
-
-BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
\ No newline at end of file

From 140d28b6b3165ad4b2b3ccd7ff5eea203481cc34 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Sun, 9 Mar 2014 15:42:51 +0000
Subject: [PATCH 068/108] plenty of new stuff

---
 src/tactic/portfolio/default_tactic.cpp       |   1 +
 src/tactic/portfolio/smt_strategic_solver.cpp |   5 +-
 src/tactic/sls/sls_evaluator.h                | 323 ++++++++-
 src/tactic/sls/sls_tactic.cpp                 | 661 ++++++++++++++++--
 src/tactic/sls/sls_tracker.h                  | 345 ++++++++-
 versions/z3-wsat-0.01.txt                     |   4 +-
 versions/z3-wsat-0.01b.txt                    |   4 +-
 7 files changed, 1235 insertions(+), 108 deletions(-)

diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index b28b7bec0..53da9a159 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -33,6 +33,7 @@ Notes:
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
                                         cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
+  //                                      cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),
diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index 586c3a349..f63b4fd8c 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -37,11 +37,14 @@ Notes:
 #include"horn_tactic.h"
 #include"smt_solver.h"
 
+#include"sls_tactic.h"
+
 tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
-	    return mk_qfbv_tactic(m, p);
+   //     return mk_qfbv_tactic(m, p);
+        return mk_qfbv_sls_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
     else if (logic=="QF_LIA")
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 61305386e..eec9524a9 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -34,6 +34,9 @@ class sls_evaluator {
     powers              & m_powers;
     expr_ref_buffer       m_temp_exprs;
     vector<ptr_vector<expr> > m_traversal_stack;
+#if _EARLY_PRUNE_
+    vector<ptr_vector<expr> > m_traversal_stack_bool;
+#endif
 
 public:
     sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : 
@@ -519,11 +522,15 @@ public:
         }    
     }
 
-    void run_update(unsigned cur_depth) {
+    void run_serious_update(unsigned cur_depth) {
         // precondition: m_traversal_stack contains the entry point(s)
         expr_fast_mark1 visited;
         mpz new_value;
 
+#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
+		double new_score;
+#endif
+
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -533,8 +540,92 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-                m_tracker.set_score(cur, m_tracker.score(cur));
 
+#if _REAL_RS_ || _REAL_PBFS_
+				if (!m_tracker.has_uplinks(cur))
+				{
+					if (m_mpz_manager.eq(new_value,m_one))
+						m_tracker.make_assertion(cur);
+					else
+						m_tracker.break_assertion(cur);
+				}
+#endif
+
+#if _EARLY_PRUNE_
+				new_score = m_tracker.score(cur);
+#if _CACHE_TOP_SCORE_
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+				m_tracker.set_score(cur, new_score);
+				m_tracker.set_score_prune(cur, new_score);
+#else
+#if _CACHE_TOP_SCORE_
+				new_score = m_tracker.score(cur);
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+				m_tracker.set_score(cur, new_score);
+#else
+				m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+#endif			
+                if (m_tracker.has_uplinks(cur)) {
+                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                    for (unsigned j = 0; j < ups.size(); j++) {
+                        expr * next = ups[j];
+                        unsigned next_d = m_tracker.get_distance(next);
+                        SASSERT(next_d < cur_depth);
+                        if (!visited.is_marked(next)) {
+                            m_traversal_stack[next_d].push_back(next);
+                            visited.mark(next);
+                        }
+                    }
+                }
+            }
+
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        m_mpz_manager.del(new_value);
+    }
+
+    void run_update(unsigned cur_depth) {
+        // precondition: m_traversal_stack contains the entry point(s)
+        expr_fast_mark1 visited;
+        mpz new_value;
+
+#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
+		double new_score;
+#endif
+
+        SASSERT(cur_depth < m_traversal_stack.size());
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
+
+            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+                expr * cur = cur_depth_exprs[i];
+
+                (*this)(to_app(cur), new_value);
+                m_tracker.set_value(cur, new_value);
+#if _EARLY_PRUNE_
+				new_score = m_tracker.score(cur);
+#if _CACHE_TOP_SCORE_
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+				m_tracker.set_score(cur, new_score);
+				m_tracker.set_score_prune(cur, new_score);
+#else
+#if _CACHE_TOP_SCORE_
+				new_score = m_tracker.score(cur);
+				if (!m_tracker.has_uplinks(cur))
+					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+				m_tracker.set_score(cur, new_score);
+#else
+				m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+#endif			
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -569,8 +660,11 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-
+#if _REAL_RS_ || _REAL_PBFS_
+		run_serious_update(max_depth);
+#else
         run_update(max_depth);
+#endif
     }
 
     void update(func_decl * fd, const mpz & new_value) {
@@ -584,6 +678,196 @@ public:
         run_update(cur_depth);
     }
 
+    void serious_update(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+        if (m_traversal_stack.size() <= cur_depth) 
+            m_traversal_stack.resize(cur_depth+1);
+        m_traversal_stack[cur_depth].push_back(ep);
+
+        run_serious_update(cur_depth);
+    }
+
+#if _EARLY_PRUNE_
+    unsigned run_update_bool_prune(unsigned cur_depth) {
+        expr_fast_mark1 visited;
+
+		double prune_score, new_score;
+		unsigned pot_benefits = 0;
+ 		SASSERT(cur_depth < m_traversal_stack_bool.size());
+ 
+        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+
+        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+            expr * cur = cur_depth_exprs[i];
+
+			new_score = m_tracker.score(cur); 
+#if _CACHE_TOP_SCORE_
+			if (!m_tracker.has_uplinks(cur))
+				m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+#endif
+			prune_score = m_tracker.get_score_prune(cur);
+            m_tracker.set_score(cur, new_score);
+
+			if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+				pot_benefits = 1;
+			if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+				pot_benefits = 1;
+
+            if (m_tracker.has_uplinks(cur)) {
+                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                for (unsigned j = 0; j < ups.size(); j++) {
+                    expr * next = ups[j];
+                    unsigned next_d = m_tracker.get_distance(next);
+                    SASSERT(next_d < cur_depth);
+                    if (!visited.is_marked(next)) {
+						m_traversal_stack_bool[next_d].push_back(next);
+                        visited.mark(next);
+                    }
+                }
+            }
+			else
+			{
+			}
+		}
+
+		cur_depth_exprs.reset();
+        cur_depth--;
+ 
+		while (cur_depth != static_cast<unsigned>(-1)) {
+			ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+			if (pot_benefits)
+			{
+				unsigned cur_size = cur_depth_exprs.size();
+				for (unsigned i = 0; i < cur_size; i++) {
+					expr * cur = cur_depth_exprs[i];
+
+#if _CACHE_TOP_SCORE_
+					new_score = m_tracker.score(cur); 
+					if (!m_tracker.has_uplinks(cur))
+						m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+					m_tracker.set_score(cur, new_score);
+#else
+					m_tracker.set_score(cur, m_tracker.score(cur));
+#endif
+					if (m_tracker.has_uplinks(cur)) {
+						ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+						for (unsigned j = 0; j < ups.size(); j++) {
+							expr * next = ups[j];
+							unsigned next_d = m_tracker.get_distance(next);
+							SASSERT(next_d < cur_depth);
+							if (!visited.is_marked(next)) {
+								m_traversal_stack_bool[next_d].push_back(next);
+								visited.mark(next);
+							}
+						}
+					}
+				}
+			}
+			cur_depth_exprs.reset();
+			cur_depth--;
+		}
+
+		return pot_benefits;
+    }
+
+    void run_update_prune(unsigned max_depth) {
+        // precondition: m_traversal_stack contains the entry point(s)
+        expr_fast_mark1 visited;
+        mpz new_value;
+
+		unsigned cur_depth = max_depth;
+        SASSERT(cur_depth < m_traversal_stack.size());
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
+
+            for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+                expr * cur = cur_depth_exprs[i];
+
+                (*this)(to_app(cur), new_value);
+                m_tracker.set_value(cur, new_value);
+				// should always have uplinks ...
+                if (m_tracker.has_uplinks(cur)) {
+                    ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                    for (unsigned j = 0; j < ups.size(); j++) {
+                        expr * next = ups[j];
+                        unsigned next_d = m_tracker.get_distance(next);
+                        SASSERT(next_d < cur_depth);
+                        if (!visited.is_marked(next)) {
+							if (m_manager.is_bool(next))
+								m_traversal_stack_bool[max_depth].push_back(next);
+							else
+								m_traversal_stack[next_d].push_back(next);
+                            visited.mark(next);
+                        }
+                    }
+                }
+            }
+
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        m_mpz_manager.del(new_value);
+    }
+
+    unsigned update_prune(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+
+		if (m_traversal_stack_bool.size() <= cur_depth)
+            m_traversal_stack_bool.resize(cur_depth+1);
+		if (m_traversal_stack.size() <= cur_depth) 
+				m_traversal_stack.resize(cur_depth+1);
+
+		if (m_manager.is_bool(ep))
+	        m_traversal_stack_bool[cur_depth].push_back(ep);
+		else
+		{
+	        m_traversal_stack[cur_depth].push_back(ep);
+			run_update_prune(cur_depth);
+		}
+		return run_update_bool_prune(cur_depth);
+    }
+#endif
+
+	void randomize_local(expr * e, unsigned int flip) {
+        ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
+
+        // Randomize _one_ candidate:
+        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
+        func_decl * fd = unsat_constants[r];
+#if _PERC_CHANGE_
+        sort * srt = fd->get_range();
+		mpz temp;
+
+		if (m_manager.is_bool(srt))
+            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+		else
+        {
+			mpz temp2, mask;
+			unsigned bv_sz = m_bv_util.get_bv_size(srt);
+			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+
+			for (unsigned bit = 0; bit < bv_sz; bit++)
+				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+	            {
+	                m_mpz_manager.set(mask, m_powers(bit));
+					m_mpz_manager.bitwise_xor(temp, mask, temp2);
+	                m_mpz_manager.set(temp, temp2);
+		        }
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(temp2);
+		}
+#else
+		mpz temp = m_tracker.get_random(fd->get_range());
+#endif
+		update(fd, temp);
+        m_mpz_manager.del(temp);
+    } 
+
      void randomize_local(goal_ref const & g, unsigned int flip) {
         ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
 
@@ -603,8 +887,37 @@ public:
         // Randomize _one_ candidate:
         unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
         func_decl * fd = unsat_constants[r];
-        mpz temp = m_tracker.get_random(fd->get_range());
-        update(fd, temp);
+#if _PERC_CHANGE_
+        sort * srt = fd->get_range();
+		mpz temp;
+
+		if (m_manager.is_bool(srt))
+            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+		else
+        {
+			mpz temp2, mask;
+			unsigned bv_sz = m_bv_util.get_bv_size(srt);
+			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+
+			for (unsigned bit = 0; bit < bv_sz; bit++)
+				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+	            {
+	                m_mpz_manager.set(mask, m_powers(bit));
+					m_mpz_manager.bitwise_xor(temp, mask, temp2);
+	                m_mpz_manager.set(temp, temp2);
+		        }
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(temp2);
+		}
+#else
+		mpz temp = m_tracker.get_random(fd->get_range());
+#endif
+
+#if _REAL_RS_ || _REAL_PBFS_
+		serious_update(fd, temp);
+#else
+		update(fd, temp);
+#endif
         m_mpz_manager.del(temp);
 
         TRACE("sls", /*tout << "Randomization candidates: ";
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index c194af267..a08588a51 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -35,16 +35,102 @@ Notes:
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
 
-#define _CNF_ 0
-#define _BFS_ 1
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
 #define _FOCUS_ 1
+
+// do we use restarts?
+// 0 = no, otherwise the value defines the maximum number of moves
 #define _RESTARTS_ 0
-#define _TIMELIMIT_ 30
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
 #define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
 #define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
 #define _VNS_ 0
-#define _WEIGHT_DIST_ 3
-#define _WEIGHT_DIST_FACTOR_ 0.1
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 0
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.25
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 0
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 0.01
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+#define _PROBABILISTIC_UCT_ 0
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 1
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 1
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 1
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 1
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
+	InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+	InvalidConfiguration;
+#endif
+
 
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
@@ -57,12 +143,17 @@ class sls_tactic : public tactic {
         stopwatch       m_stopwatch;    
         unsigned        m_full_evals;
         unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+
         stats() :
             m_restarts(0),
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
+			m_umins(0),
+			m_mul2s(0),
+			m_mul3s(0),
+			m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -92,7 +183,9 @@ class sls_tactic : public tactic {
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;        
+		ptr_vector<mpz> m_old_values;
+		
+        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
 
         imp(ast_manager & m, params_ref const & p, stats & s) : 
             m_manager(m),
@@ -174,13 +267,20 @@ class sls_tactic : public tactic {
             #else
             double top_sum = 0.0;
             unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                top_sum += m_tracker.get_score(g->form(i));
+			for (unsigned i = 0; i < sz; i++) {
+				expr * e = g->form(i);
+                top_sum += m_tracker.get_score(e);
             }
-            TRACE("sls_top", tout << "Score distribution:"; 
+
+			TRACE("sls_top", tout << "Score distribution:"; 
                                     for (unsigned i = 0; i < sz; i++)
                                         tout << " " << m_tracker.get_score(g->form(i));
                                     tout << " AVG: " << top_sum / (double) sz << std::endl; );
+
+#if _CACHE_TOP_SCORE_
+			m_tracker.set_top_sum(top_sum);
+#endif
+
             return top_sum / (double) sz;
             #endif
         }
@@ -191,22 +291,54 @@ class sls_tactic : public tactic {
             return top_score(g);
         }
 
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
+        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+			m_evaluator.serious_update(fd, new_value);
             m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+			return (m_tracker.get_top_sum() / g->size());
+#else
             return top_score(g);
+#endif
         }
 
+        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+			m_evaluator.update(fd, new_value);
+            m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+			return (m_tracker.get_top_sum() / g->size());
+#else
+            return top_score(g);
+#endif
+        }
+
+#if _EARLY_PRUNE_
+        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_stats.m_incr_evals++;
+			if (m_evaluator.update_prune(fd, new_value))
+#if _CACHE_TOP_SCORE_
+				return (m_tracker.get_top_sum() / g->size());
+#else
+	            return top_score(g);
+#endif
+			else
+				return 0.0;
+        }
+#endif
+
+		// checks whether the score outcome of a given move is better than the previous score
         bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
-        
+
             #ifdef Z3DEBUG
             mpz old_value;
             m_mpz_manager.set(old_value, m_tracker.get_value(fd));
             #endif
 
+#if _EARLY_PRUNE_
+            double r = incremental_score_prune(g, fd, temp);
+#else
             double r = incremental_score(g, fd, temp);
-        
+#endif   
             #ifdef Z3DEBUG
             TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
                                         " --> " << r << std::endl; );
@@ -214,6 +346,22 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(old_value);
             #endif
 
+//            if (r >= best_score) {
+            if (r > best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+		// same as what_if, but only applied to the score of a specific atom, not the total score
+        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+            m_evaluator.update(fd, temp);
+			double r = m_tracker.get_score(e);
             if (r >= best_score) {
                 best_score = r;
                 best_const = fd_inx;            
@@ -224,7 +372,35 @@ class sls_tactic : public tactic {
             return false;
         }
 
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.add(old_value, add_value, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+			m_mpz_manager.del(temp);
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(mask2);
+
+		}
+
+		// Andreas: do we really need all those temporary mpzs?
+		void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.mul(old_value, m_two, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+			m_mpz_manager.del(temp);
+			m_mpz_manager.del(mask);
+			m_mpz_manager.del(mask2);
+        }
+
+        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            m_mpz_manager.div(old_value, m_two, result);
+        }
+
+		void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
             unsigned shift;        
             m_mpz_manager.add(old_value, m_one, incremented);
             if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
@@ -261,59 +437,73 @@ class sls_tactic : public tactic {
 
         void mk_random_move(goal_ref const & g) {
             unsigned rnd_mv = 0;
-            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-            move_type mt = (move_type) rnd_mv;
-
-            // inversion doesn't make sense, let's do a flip instead.
-            if (mt == MV_INV) mt = MV_FLIP;
+			if (m_stats.m_moves > 10000)
+				rnd_mv = 0;
 
 			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
-            mpz new_value;
-            unsigned bit = 0;
 
-            switch (mt)
-            {
-            case MV_FLIP: {
-                unsigned bv_sz = m_bv_util.get_bv_size(fd->get_range());
-                bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                break;
-            }
-            case MV_INC: 
-                mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            case MV_DEC: 
-                mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            case MV_INV:
-                mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                break;
-            default:
-                NOT_IMPLEMENTED_YET();
-            }
+			mpz new_value;
 
-            m_evaluator.update(fd, new_value);            
+			sort * srt = fd->get_range();
+            if (m_manager.is_bool(srt))
+				m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+			else
+			{
+#if _USE_ADDSUB_
+	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+				move_type mt = (move_type) rnd_mv;
 
-            TRACE("sls", tout << "Randomization candidates: ";
-                         for (unsigned i = 0; i < unsat_constants.size(); i++)
-                             tout << unsat_constants[i]->get_name() << ", ";
-                         tout << std::endl;
-                         tout << "Random move: ";
-                         switch (mt) {
-                         case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                         case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                         case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                         case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                         }
-                         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+				// inversion doesn't make sense, let's do a flip instead.
+				if (mt == MV_INV) mt = MV_FLIP;
+#else
+				mt = MV_FLIP;
+#endif
+				unsigned bit = 0;
 
-            m_mpz_manager.del(new_value);
-        }
+				switch (mt)
+				{
+					case MV_FLIP: {
+					unsigned bv_sz = m_bv_util.get_bv_size(srt);
+					bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+					mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+					break;
+				}
+				case MV_INC: 
+					mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				case MV_DEC: 
+					mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				case MV_INV:
+					mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+					break;
+				default:
+					NOT_IMPLEMENTED_YET();
+				}
 
+				TRACE("sls", tout << "Randomization candidates: ";
+							 for (unsigned i = 0; i < unsat_constants.size(); i++)
+								 tout << unsat_constants[i]->get_name() << ", ";
+							 tout << std::endl;
+							 tout << "Random move: ";
+							 switch (mt) {
+							 case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+							 case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+							 case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+							 case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+							 }
+							 tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+			}
+
+			m_evaluator.update(fd, new_value);            
+			m_mpz_manager.del(new_value);
+		}
+
+		// will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -359,6 +549,7 @@ class sls_tactic : public tactic {
                 SASSERT(check == score);
             }
 
+			// we can either check the condition once in the beginning or check it repeatedly after every bit
 #if _VNS_ == 1
 			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
 #else
@@ -390,9 +581,13 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
+		// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+			mpz temp2;
+#endif
             unsigned bv_sz;
             double new_score = score;
 
@@ -403,8 +598,12 @@ class sls_tactic : public tactic {
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-                    // What would happen if we flipped bit #i ?                
+#if _SKIP_BITS_
+				for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+#else
+				for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+					// What would happen if we flipped bit #i ?                
                     mk_flip(srt, old_value, j, temp);                
 
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
@@ -414,7 +613,8 @@ class sls_tactic : public tactic {
                 }
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
+#if _USE_ADDSUB_
+					if (!m_mpz_manager.is_even(old_value)) { 
                         // for odd values, try +1
                         mk_inc(bv_sz, old_value, temp);
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
@@ -426,16 +626,99 @@ class sls_tactic : public tactic {
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                             move = MV_DEC;
                     }
-
+#endif
                     // try inverting
                     mk_inv(bv_sz, old_value, temp);
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                         move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+                    mk_inc(bv_sz, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+                    // try multiplication by 2
+                    mk_mul2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_MUL2;
+
+#if _USE_MUL3_
+                    // try multiplication by 3
+                    mk_add(bv_sz, old_value, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_MUL3;
+#endif
+
+                    // try division by 2
+                    mk_div2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_DIV2;
+#endif
                 }
 
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
+				// Andreas: does not hold anymore now that we use top level score caching
+                //SASSERT(check == score);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+#if _USE_MUL3_
+            m_mpz_manager.del(temp2);
+#endif
+			return new_score;
+        }        
+
+		// same as find_best_move but only considers the score of the current expression instead of the overall score
+		double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz;
+			double new_score = m_tracker.get_score(e);
+			// Andreas: tie breaking not implemented yet
+			// double tie_score = top_score(g);
+            for (unsigned i = 0; i < to_evaluate.size(); i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+                for (unsigned j = 0; j < bv_sz; j++) {
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+                }
+
+                // reset to what it was before
+	            m_evaluator.update(fd, old_value);
             }
 
             m_mpz_manager.del(old_value);
@@ -443,7 +726,150 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
-        lbool search(goal_ref const & g) {        
+		// first try of intensification ... does not seem to be efficient
+		bool handle_plateau(goal_ref const & g)
+		{
+			unsigned sz = g->size();
+#if _BFS_
+			unsigned pos = m_stats.m_moves % sz;
+#else
+			unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+			expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+	        if (!e)
+				return 0;
+
+			expr * q = m_tracker.get_unsat_expression(e);
+			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+			for (unsigned i = 0; i < to_evaluate.size(); i++)
+			{
+				m_tracker.get_value(to_evaluate[i]);
+				m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+			}            
+			unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+			for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+			{
+				// Andreas: Could be extended to use (best) score but this is computationally more expensive.
+                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
+
+                if (new_const == static_cast<unsigned>(-1)) {
+					// Andreas: Actually this should never happen.
+					NOT_IMPLEMENTED_YET();
+                } else {
+                    m_stats.m_moves++;
+                    func_decl * fd = to_evaluate[new_const];
+
+                    switch (move) {
+                    case MV_FLIP: m_stats.m_flips++; break;
+                    case MV_INC: m_stats.m_incs++; break;
+                    case MV_DEC: m_stats.m_decs++; break;
+                    case MV_INV: m_stats.m_invs++; break;
+                    case MV_UMIN: m_stats.m_umins++; break;
+					case MV_MUL2: m_stats.m_mul2s++; break;
+					case MV_MUL3: m_stats.m_mul3s++; break;
+					case MV_DIV2: m_stats.m_div2s++; break;
+                    }
+                    
+					m_evaluator.update(fd, new_value);
+                }
+
+				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+					return 1;
+			}
+
+			for (unsigned i = 0; i < to_evaluate.size(); i++)
+				m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+
+			m_old_values.reset();
+
+			return 0;
+		}
+
+		// what_if version needed in the context of 2nd intensification try, combining local and global score
+        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
+                        double & best_score, mpz & best_value, unsigned i) {
+        
+            double global_score = incremental_score(g, fd, temp);
+			double local_score = m_tracker.get_score(e);
+            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+			if (new_score >= best_score) {
+                best_score = new_score;
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+		// find_best_move version needed in the context of 2nd intensification try
+        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+		{
+			mpz old_value, temp;
+            double best_score = 0;
+
+            sort * srt = fd->get_range();
+            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+			for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+                mk_flip(srt, old_value, j, temp);                
+                what_if(g, e, fd, temp, best_score, best_value, i); 
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+
+			return best_score;
+        }        
+
+		// second try to use intensification ... also not very effective
+		bool handle_plateau(goal_ref const & g, double old_score)
+		{
+			unsigned sz = g->size();
+#if _BFS_
+			unsigned new_const = m_stats.m_moves % sz;
+#else
+			unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+			expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+	        if (!e)
+				return 0;
+
+			expr * q = m_tracker.get_unsat_expression(e);
+			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+			new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+			func_decl * fd = to_evaluate[new_const];
+
+			mpz new_value;
+			//m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+			unsigned new_bit = 0;        
+			double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+			
+			for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+			{
+                new_score = find_best_move_local(g, q, fd, new_value, i);
+
+                m_stats.m_moves++;
+                m_stats.m_flips++;
+
+				global_score = incremental_score(g, fd, new_value);
+     			local_score = m_tracker.get_score(q);
+
+				SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+					return 1;
+			}
+
+			return 0;
+		}
+
+		// main search loop
+		lbool search(goal_ref const & g) {        
             lbool res = l_undef;
             double score = 0.0, old_score = 0.0;
             unsigned new_const = (unsigned)-1, new_bit = 0;        
@@ -463,16 +889,48 @@ class sls_tactic : public tactic {
 #if _RESTARTS_
 			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
+					if (m_stats.m_moves == 5590)
                     checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
             
+#if _TYPE_RSTEP_
+					if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+					{
+#if _TYPE_RSTEP_ == 1
+						m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+						mk_random_move(g);
+#endif
+                        score = top_score(g);
+
+	                    if (score >= 1.0) {
+	                        bool all_true = true;
+	                        for (unsigned i = 0; i < g->size() && all_true; i++)
+	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+	                                all_true=false;
+	                        if (all_true) {
+	                            res = l_true; // sat
+	                            goto bailout;
+							} else
+								TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+						}
+					}
+#endif
                     old_score = score;
                     new_const = (unsigned)-1;
                         
 					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-
+					if (!to_evaluate.size())
+					{
+						res = l_true;
+						goto bailout;
+					}
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
@@ -525,9 +983,17 @@ class sls_tactic : public tactic {
                         case MV_INC: m_stats.m_incs++; break;
                         case MV_DEC: m_stats.m_decs++; break;
                         case MV_INV: m_stats.m_invs++; break;
+                        case MV_UMIN: m_stats.m_umins++; break;
+						case MV_MUL2: m_stats.m_mul2s++; break;
+						case MV_MUL3: m_stats.m_mul3s++; break;
+						case MV_DIV2: m_stats.m_div2s++; break;
                         }
                     
-                        score = incremental_score(g, fd, new_value);    
+#if _REAL_RS_ || _REAL_PBFS_
+						score = serious_score(g, fd, new_value);
+#else
+						score = incremental_score(g, fd, new_value);    
+#endif
 
                         TRACE("sls", tout << "Score distribution:"; 
                                         for (unsigned i = 0; i < g->size(); i++)
@@ -535,9 +1001,10 @@ class sls_tactic : public tactic {
                                         tout << " TOP: " << score << std::endl; );                        
                     }
 
-                    if (score >= 1.0) {
+                    if (score >= 0.99999) {
+//                    if (score >= 1.0) {
                         // score could theoretically be imprecise.
-						// Andreas: Can it only be imprecise in one direction?
+						// Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -568,10 +1035,26 @@ class sls_tactic : public tactic {
 					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
                     //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
+#if _INTENSIFICATION_
+						handle_plateau(g, score);
+						//handle_plateau(g);
+#else
 						m_evaluator.randomize_local(g, m_stats.m_moves);
-                        //mk_random_move(g);
+#endif
+						//mk_random_move(g);
                         score = top_score(g);
-                    //}
+
+	                    if (score >= 1.0) {
+	                        bool all_true = true;
+	                        for (unsigned i = 0; i < g->size() && all_true; i++)
+	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+	                                all_true=false;
+	                        if (all_true) {
+	                            res = l_true; // sat
+	                            goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
                 }
             }
 
@@ -587,6 +1070,37 @@ class sls_tactic : public tactic {
                 return;
             }
 
+			verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+			verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+			verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+			verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+			verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+			verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+			verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+			verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+			verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+			verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+			verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+			verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+			verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+			verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+			verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+			verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+			verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+			verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+			verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+			verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+			verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+			verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+			verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+			verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+			verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+			verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+			verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+			
+#if _WEIGHT_DIST_ == 4
+					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
@@ -740,13 +1254,8 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-#if _CNF_
-						// Andreas: We will probably never use this. CNF sucks.
-                        mk_cnf_tactic(m, p));
-#else
 						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
-#endif
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 1061bd90e..b26912e5c 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -28,21 +28,32 @@ class sls_tracker {
     random_gen            m_rng;
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
-    mpz                   m_zero, m_one, m_two;   
+    mpz                   m_zero, m_one, m_two;
 	    
     struct value_score { 
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0) { };
+#if _EARLY_PRUNE_
+		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+#else
+		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
+#endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
+#if _EARLY_PRUNE_
+		double score_prune;
+		unsigned has_pos_occ;
+		unsigned has_neg_occ;
+#endif
         unsigned distance; // max distance from any root
+		unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
+			touched = other.touched;
             return *this;
         }
     };
@@ -60,6 +71,20 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
+#if _UCT_
+	unsigned              m_touched;
+#endif
+#if _REAL_RS_ || _REAL_PBFS_
+	ptr_vector<expr>	  m_unsat_expr;
+	obj_map<expr, unsigned>	m_where_false;
+	expr**					m_list_false;
+#endif
+#if _CACHE_TOP_SCORE_
+	double				  m_top_sum;
+#endif
+#if _WEIGHT_DIST_ == 4
+	double				  m_weight_dist_factor;
+#endif
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -79,6 +104,26 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+#if _WEIGHT_DIST_ == 4
+	inline void set_weight_dist_factor(double val) {
+		m_weight_dist_factor = val;
+	}
+#endif
+
+#if _CACHE_TOP_SCORE_
+	inline void adapt_top_sum(double add, double sub) {
+		m_top_sum += add - sub;
+	}
+
+	inline void set_top_sum(double new_score) {
+		m_top_sum = new_score;
+	}
+
+	inline double get_top_sum() {
+		return m_top_sum;
+	}
+#endif
+
     inline void set_value(expr * n, const mpz & r) {
         SASSERT(m_scores.contains(n));
         m_mpz_manager.set(m_scores.find(n).value, r);
@@ -123,6 +168,28 @@ public:
         return get_score(ep);
     }
 
+#if _EARLY_PRUNE_
+    inline void set_score_prune(expr * n, double score) {
+        SASSERT(m_scores.contains(n));
+        m_scores.find(n).score_prune = score;
+    }
+
+	inline double & get_score_prune(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).score_prune;
+    }
+
+	inline unsigned has_pos_occ(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).has_pos_occ;
+ 	}
+
+	inline unsigned has_neg_occ(expr * n) {
+        SASSERT(m_scores.contains(n));
+        return m_scores.find(n).has_neg_occ;
+ 	}
+#endif
+
     inline unsigned get_distance(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).distance;
@@ -297,7 +364,7 @@ public:
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
 			// Andreas: Maybe not fully correct.
-#if _FOCUS_ == 2
+#if _FOCUS_ == 2 || _INTENSIFICATION_
 			initialize_recursive(e);
 #endif
             ptr_vector<func_decl> t;
@@ -310,8 +377,57 @@ public:
         calculate_expr_distances(g);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
+
+#if _REAL_RS_ || _REAL_PBFS_
+		m_list_false = new expr*[sz];
+        for (unsigned i = 0; i < sz; i++)
+	  		if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+				break_assertion(g->form(i));
+#endif
+
+#if _EARLY_PRUNE_
+        for (unsigned i = 0; i < sz; i++)
+	  		setup_occs(g->form(i));
+#endif
+
+#if _UCT_
+		m_touched = 1;
+#endif
     }
 
+#if _REAL_RS_ || _REAL_PBFS_
+	void make_assertion(expr * e)
+	{
+		if (m_where_false.contains(e))
+		{
+			unsigned pos = m_where_false.find(e);
+			m_where_false.erase(e);
+			if (pos != m_where_false.size())
+			{
+				expr * q = m_list_false[m_where_false.size()];
+				m_list_false[pos] = q;
+				m_where_false.find(q) = pos;
+			}
+//			printf("Going in %d\n", m_where_false.size());
+		}
+		//if (m_unsat_expr.contains(e))
+			//m_unsat_expr.erase(e);
+	}
+
+	void break_assertion(expr * e)
+	{
+		if (!m_where_false.contains(e))
+		{
+			unsigned pos = m_where_false.size();
+			m_list_false[pos] = e;
+			m_where_false.insert(e, pos);
+	//		printf("Going in %d\n", m_where_false.size());
+		}
+		//if (!m_unsat_expr.contains(e))
+			//m_unsat_expr.push_back(e);
+	}
+#endif
+
     void show_model(std::ostream & out) {
         unsigned sz = get_num_constants();
         for (unsigned i = 0; i < sz; i++) {
@@ -420,10 +536,45 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
     }              
 
+#if _EARLY_PRUNE_
+	void setup_occs(expr * n, bool negated = false) {
+		if (m_manager.is_bool(n))
+		{
+			if (m_manager.is_and(n) || m_manager.is_or(n))
+			{
+	            SASSERT(!negated);
+	            app * a = to_app(n);
+	            expr * const * args = a->get_args();
+	            for (unsigned i = 0; i < a->get_num_args(); i++)
+					setup_occs(args[i]);
+			}
+			else if (m_manager.is_not(n))
+			{
+	            SASSERT(!negated);
+	            app * a = to_app(n);
+	            SASSERT(a->get_num_args() == 1);
+	            expr * child = a->get_arg(0);
+	            if (m_manager.is_and(child) || m_manager.is_or(child))
+	                NOT_IMPLEMENTED_YET();
+				setup_occs(child, true);
+			}
+			else
+			{
+				if (negated)
+					m_scores.find(n).has_neg_occ = 1;
+				else
+					m_scores.find(n).has_pos_occ = 1;
+			}
+		}
+        else
+            NOT_IMPLEMENTED_YET();
+    }
+#endif
+
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
-        double res = 0.0;
+		double res = 0.0;
             
         if (is_uninterp_const(n)) {
             const mpz & r = get_value(n);
@@ -488,7 +639,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-
+			
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -648,6 +799,7 @@ public:
 #if _WEIGHT_DIST_
 		app * a = to_app(n);
 		family_id afid = a->get_family_id();
+
 		if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
@@ -656,13 +808,14 @@ public:
 		res *= res;
 #elif _WEIGHT_DIST_ == 3
 		if (res < 1.0) res = 0.0;
+#elif _WEIGHT_DIST_ == 4
+		if (res < 1.0) res *= m_weight_dist_factor;
 #endif
 
-
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-
+	
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -708,6 +861,44 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
+	expr * get_unsat_expression(expr * e) {
+		if (m_manager.is_bool(e)) {
+			if (m_manager.is_and(e) || m_manager.is_or(e)) {
+				app * a = to_app(e);
+				expr * const * args = a->get_args();
+			    // Andreas: might be used for guided branching
+				//for (unsigned i = 0; i < a->get_num_args(); i++) {
+					//double cur = get_score(args[i]);
+				//}
+				// Andreas: A random number is better here since reusing flip will cause patterns.
+				unsigned int sz = a->get_num_args();
+				unsigned int pos = get_random_uint(16) % sz;
+				for (unsigned int i = pos; i < sz; i++) {
+	                expr * q = args[i];
+	                if (m_mpz_manager.neq(get_value(q), m_one))
+			            return get_unsat_expression(q);
+				}
+				for (unsigned int i = 0; i < pos; i++) {
+					expr * q = args[i];
+	                if (m_mpz_manager.neq(get_value(q), m_one))
+			            return get_unsat_expression(q);
+	            }
+	        }
+		}
+		return e;
+	}
+
+	ptr_vector<func_decl> & get_constants(expr * e) {
+        ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+        unsigned sz = this_decls.size();
+        for (unsigned i = 0; i < sz; i++) {
+            func_decl * fd = this_decls[i];
+            if (!m_temp_constants.contains(fd))
+                m_temp_constants.push_back(fd);
+        }
+        return m_temp_constants;
+	}
+
 	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
@@ -743,7 +934,6 @@ public:
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
 			if (!q)
 				return m_temp_constants;
-
 			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
@@ -754,6 +944,19 @@ public:
 	        return m_temp_constants;
 	}
 
+	ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
+			if (!e)
+				return m_temp_constants;
+			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz = this_decls.size();
+            for (unsigned j = 0; j < sz; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+	        return m_temp_constants;
+	}
+
 	ptr_vector<func_decl> & go_deeper(expr * e) {
 			if (m_manager.is_bool(e)) {
 				if (m_manager.is_and(e)) {
@@ -812,44 +1015,138 @@ public:
 		return go_deeper(q);
 	}
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+	ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
-            return get_constants();
+			if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+				return m_temp_constants;
+			else
+	            return get_constants();
         }
         else {
             m_temp_constants.reset();
 #if _FOCUS_ == 1
-#if _BFS_ == 3
-			unsigned int pos = 0;
-			double max = get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
+#if _UCT_
+			unsigned pos = -1;
+			value_score vscore;
+#if _PROBABILISTIC_UCT_
+			double sum_score = 0.0;
+			unsigned start_index = get_random_uint(16) % sz;
+			for (unsigned i = start_index; i < sz; i++)
+			{
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+					sum_score += q;
+					if (rand() <= (q * RAND_MAX / sum_score) + 1)
+						pos = i;
+				}	
+			}
+			for (unsigned i = 0; i < start_index; i++)
+			{
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+					sum_score += q;
+					if (rand() <= (q * RAND_MAX / sum_score) + 1)
+						pos = i;
+				}	
+			}
+#else
+			double max = -1.0;
+			for (unsigned i = 0; i < sz; i++) {
+				expr * e = g->form(i);
+				vscore = m_scores.find(e);
+#if _UCT_ == 1
+				double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#elif _UCT_ == 2
+				double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#endif
+				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+            }
+#endif
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+
+#if _UCT_ == 1
+			m_scores.find(g->form(pos)).touched++;
+			m_touched++;
+#elif _UCT_ == 2
+			m_scores.find(g->form(pos)).touched = flip; 
+#endif
+			expr * e = g->form(pos);
+
+#elif _BFS_ == 3
+			unsigned int pos = -1;
+			double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
 				expr * e = g->form(i);
                 double q = get_score(e);
 				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
 #elif _BFS_ == 2
-			unsigned int pos = 0;
-			double min = get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
+			unsigned int pos = -1;
+			double min = 2.0;
+            for (unsigned i = 0; i < sz; i++) {
 				expr * e = g->form(i);
                 double q = get_score(e);
 				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
             }
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
 #elif _BFS_ == 1
-			unsigned int pos = flip % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = flip % m_constants.size();
+			unsigned int pos = flip % sz;
+			expr * e = get_unsat_assertion(g, sz, pos);
+#elif _UNIFORM_RANDOM_
+			unsigned cnt_unsat = 0, pos = -1;
+			for (unsigned i = 0; i < sz; i++)
+				if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+			if (pos == static_cast<unsigned>(-1))
+				return m_temp_constants;
+			expr * e = g->form(pos);
+#elif _REAL_RS_
+			//unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+			//expr * e = get_unsat_assertion(g, sz, pos);
+			//expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+			sz = m_where_false.size();
+			if (sz == 0)
+				return m_temp_constants;
+			else
+				expr * e = m_list_false[get_random_uint(16) % sz];
+#elif _REAL_PBFS_
+			//unsigned pos = m_false_list[flip % m_cnt_false];
+			//expr * e = get_unsat_assertion(g, sz, pos);
+			//expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+			sz = m_where_false.size();
+			if (sz == 0)
+				return m_temp_constants;
+			else
+				expr * e = m_list_false[flip % sz];
 #else
-			unsigned int pos = get_random_uint(16) % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = get_random_uint(16) % m_constants.size();
+			unsigned int pos = get_random_uint(16) % sz;
+			expr * e = get_unsat_assertion(g, sz, pos);
 #endif
-			return get_unsat_constants_walksat(g, sz, pos);
+			return get_unsat_constants_walksat(e);
 #elif _FOCUS_ == 2
 #if _BFS_
-			unsigned int pos = flip % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = flip % m_constants.size();
+			unsigned int pos = flip % sz;
 #else
-			unsigned int pos = get_random_uint(16) % m_constants.size();
+			// I guess it was buggy ...
+			// unsigned int pos = get_random_uint(16) % m_constants.size();
+			unsigned int pos = get_random_uint(16) % sz;
 #endif
 			return get_unsat_constants_crsat(g, sz, pos);
 #else
diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt
index 141193f76..fec38518d 100644
--- a/versions/z3-wsat-0.01.txt
+++ b/versions/z3-wsat-0.01.txt
@@ -9,4 +9,6 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
+
+BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt
index 2c0c0e7ad..8bcf2ffeb 100644
--- a/versions/z3-wsat-0.01b.txt
+++ b/versions/z3-wsat-0.01b.txt
@@ -9,4 +9,6 @@ No restarts.
 #define _RESTARTS_ 0
 #define _TIMELIMIT_ 300
 #define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
+#define _SCORE_OR_MUL_ 0
+
+BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file

From 664fa82c6cb752b08a3788af542a999464f0b930 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 09:40:01 +0000
Subject: [PATCH 069/108] removed tabs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_evaluator.h | 268 ++++++-------
 src/tactic/sls/sls_tactic.cpp  | 572 ++++++++++++++--------------
 src/tactic/sls/sls_tracker.h   | 672 ++++++++++++++++-----------------
 3 files changed, 756 insertions(+), 756 deletions(-)

diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index eec9524a9..cdb08038f 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -528,7 +528,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -542,33 +542,33 @@ public:
                 m_tracker.set_value(cur, new_value);
 
 #if _REAL_RS_ || _REAL_PBFS_
-				if (!m_tracker.has_uplinks(cur))
-				{
-					if (m_mpz_manager.eq(new_value,m_one))
-						m_tracker.make_assertion(cur);
-					else
-						m_tracker.break_assertion(cur);
-				}
+                if (!m_tracker.has_uplinks(cur))
+                {
+                    if (m_mpz_manager.eq(new_value,m_one))
+                        m_tracker.make_assertion(cur);
+                    else
+                        m_tracker.break_assertion(cur);
+                }
 #endif
 
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -596,7 +596,7 @@ public:
         mpz new_value;
 
 #if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
-		double new_score;
+        double new_score;
 #endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
@@ -609,23 +609,23 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 #if _EARLY_PRUNE_
-				new_score = m_tracker.score(cur);
+                new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-				m_tracker.set_score(cur, new_score);
-				m_tracker.set_score_prune(cur, new_score);
+                m_tracker.set_score(cur, new_score);
+                m_tracker.set_score_prune(cur, new_score);
 #else
 #if _CACHE_TOP_SCORE_
-				new_score = m_tracker.score(cur);
-				if (!m_tracker.has_uplinks(cur))
-					m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-				m_tracker.set_score(cur, new_score);
+                new_score = m_tracker.score(cur);
+                if (!m_tracker.has_uplinks(cur))
+                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #else
-				m_tracker.set_score(cur, m_tracker.score(cur));
+                m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -661,7 +661,7 @@ public:
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
 #if _REAL_RS_ || _REAL_PBFS_
-		run_serious_update(max_depth);
+        run_serious_update(max_depth);
 #else
         run_update(max_depth);
 #endif
@@ -693,27 +693,27 @@ public:
     unsigned run_update_bool_prune(unsigned cur_depth) {
         expr_fast_mark1 visited;
 
-		double prune_score, new_score;
-		unsigned pot_benefits = 0;
- 		SASSERT(cur_depth < m_traversal_stack_bool.size());
+        double prune_score, new_score;
+        unsigned pot_benefits = 0;
+         SASSERT(cur_depth < m_traversal_stack_bool.size());
  
         ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
 
         for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
             expr * cur = cur_depth_exprs[i];
 
-			new_score = m_tracker.score(cur); 
+            new_score = m_tracker.score(cur); 
 #if _CACHE_TOP_SCORE_
-			if (!m_tracker.has_uplinks(cur))
-				m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+            if (!m_tracker.has_uplinks(cur))
+                m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
-			prune_score = m_tracker.get_score_prune(cur);
+            prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
-			if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
-				pot_benefits = 1;
-			if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
-				pot_benefits = 1;
+            if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+                pot_benefits = 1;
+            if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+                pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
                 ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -722,54 +722,54 @@ public:
                     unsigned next_d = m_tracker.get_distance(next);
                     SASSERT(next_d < cur_depth);
                     if (!visited.is_marked(next)) {
-						m_traversal_stack_bool[next_d].push_back(next);
+                        m_traversal_stack_bool[next_d].push_back(next);
                         visited.mark(next);
                     }
                 }
             }
-			else
-			{
-			}
-		}
+            else
+            {
+            }
+        }
 
-		cur_depth_exprs.reset();
+        cur_depth_exprs.reset();
         cur_depth--;
  
-		while (cur_depth != static_cast<unsigned>(-1)) {
-			ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-			if (pot_benefits)
-			{
-				unsigned cur_size = cur_depth_exprs.size();
-				for (unsigned i = 0; i < cur_size; i++) {
-					expr * cur = cur_depth_exprs[i];
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+            if (pot_benefits)
+            {
+                unsigned cur_size = cur_depth_exprs.size();
+                for (unsigned i = 0; i < cur_size; i++) {
+                    expr * cur = cur_depth_exprs[i];
 
 #if _CACHE_TOP_SCORE_
-					new_score = m_tracker.score(cur); 
-					if (!m_tracker.has_uplinks(cur))
-						m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
-					m_tracker.set_score(cur, new_score);
+                    new_score = m_tracker.score(cur); 
+                    if (!m_tracker.has_uplinks(cur))
+                        m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.set_score(cur, new_score);
 #else
-					m_tracker.set_score(cur, m_tracker.score(cur));
+                    m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-					if (m_tracker.has_uplinks(cur)) {
-						ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-						for (unsigned j = 0; j < ups.size(); j++) {
-							expr * next = ups[j];
-							unsigned next_d = m_tracker.get_distance(next);
-							SASSERT(next_d < cur_depth);
-							if (!visited.is_marked(next)) {
-								m_traversal_stack_bool[next_d].push_back(next);
-								visited.mark(next);
-							}
-						}
-					}
-				}
-			}
-			cur_depth_exprs.reset();
-			cur_depth--;
-		}
+                    if (m_tracker.has_uplinks(cur)) {
+                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                        for (unsigned j = 0; j < ups.size(); j++) {
+                            expr * next = ups[j];
+                            unsigned next_d = m_tracker.get_distance(next);
+                            SASSERT(next_d < cur_depth);
+                            if (!visited.is_marked(next)) {
+                                m_traversal_stack_bool[next_d].push_back(next);
+                                visited.mark(next);
+                            }
+                        }
+                    }
+                }
+            }
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
 
-		return pot_benefits;
+        return pot_benefits;
     }
 
     void run_update_prune(unsigned max_depth) {
@@ -777,7 +777,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-		unsigned cur_depth = max_depth;
+        unsigned cur_depth = max_depth;
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
             ptr_vector<expr> & cur_depth_exprs = m_traversal_stack[cur_depth];
@@ -787,7 +787,7 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-				// should always have uplinks ...
+                // should always have uplinks ...
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -795,10 +795,10 @@ public:
                         unsigned next_d = m_tracker.get_distance(next);
                         SASSERT(next_d < cur_depth);
                         if (!visited.is_marked(next)) {
-							if (m_manager.is_bool(next))
-								m_traversal_stack_bool[max_depth].push_back(next);
-							else
-								m_traversal_stack[next_d].push_back(next);
+                            if (m_manager.is_bool(next))
+                                m_traversal_stack_bool[max_depth].push_back(next);
+                            else
+                                m_traversal_stack[next_d].push_back(next);
                             visited.mark(next);
                         }
                     }
@@ -817,23 +817,23 @@ public:
         expr * ep = m_tracker.get_entry_point(fd);
         unsigned cur_depth = m_tracker.get_distance(ep);
 
-		if (m_traversal_stack_bool.size() <= cur_depth)
+        if (m_traversal_stack_bool.size() <= cur_depth)
             m_traversal_stack_bool.resize(cur_depth+1);
-		if (m_traversal_stack.size() <= cur_depth) 
-				m_traversal_stack.resize(cur_depth+1);
+        if (m_traversal_stack.size() <= cur_depth) 
+                m_traversal_stack.resize(cur_depth+1);
 
-		if (m_manager.is_bool(ep))
-	        m_traversal_stack_bool[cur_depth].push_back(ep);
-		else
-		{
-	        m_traversal_stack[cur_depth].push_back(ep);
-			run_update_prune(cur_depth);
-		}
-		return run_update_bool_prune(cur_depth);
+        if (m_manager.is_bool(ep))
+            m_traversal_stack_bool[cur_depth].push_back(ep);
+        else
+        {
+            m_traversal_stack[cur_depth].push_back(ep);
+            run_update_prune(cur_depth);
+        }
+        return run_update_bool_prune(cur_depth);
     }
 #endif
 
-	void randomize_local(expr * e, unsigned int flip) {
+    void randomize_local(expr * e, unsigned int flip) {
         ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
 
         // Randomize _one_ candidate:
@@ -841,30 +841,30 @@ public:
         func_decl * fd = unsat_constants[r];
 #if _PERC_CHANGE_
         sort * srt = fd->get_range();
-		mpz temp;
+        mpz temp;
 
-		if (m_manager.is_bool(srt))
+        if (m_manager.is_bool(srt))
             m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
+        else
         {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+            mpz temp2, mask;
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(temp, m_tracker.get_value(fd));
 
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
+            for (unsigned bit = 0; bit < bv_sz; bit++)
+                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+                {
+                    m_mpz_manager.set(mask, m_powers(bit));
+                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
+                    m_mpz_manager.set(temp, temp2);
+                }
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(temp2);
+        }
 #else
-		mpz temp = m_tracker.get_random(fd->get_range());
+        mpz temp = m_tracker.get_random(fd->get_range());
 #endif
-		update(fd, temp);
+        update(fd, temp);
         m_mpz_manager.del(temp);
     } 
 
@@ -889,34 +889,34 @@ public:
         func_decl * fd = unsat_constants[r];
 #if _PERC_CHANGE_
         sort * srt = fd->get_range();
-		mpz temp;
+        mpz temp;
 
-		if (m_manager.is_bool(srt))
+        if (m_manager.is_bool(srt))
             m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-		else
+        else
         {
-			mpz temp2, mask;
-			unsigned bv_sz = m_bv_util.get_bv_size(srt);
-			m_mpz_manager.set(temp, m_tracker.get_value(fd));
+            mpz temp2, mask;
+            unsigned bv_sz = m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(temp, m_tracker.get_value(fd));
 
-			for (unsigned bit = 0; bit < bv_sz; bit++)
-				if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-	            {
-	                m_mpz_manager.set(mask, m_powers(bit));
-					m_mpz_manager.bitwise_xor(temp, mask, temp2);
-	                m_mpz_manager.set(temp, temp2);
-		        }
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(temp2);
-		}
+            for (unsigned bit = 0; bit < bv_sz; bit++)
+                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
+                {
+                    m_mpz_manager.set(mask, m_powers(bit));
+                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
+                    m_mpz_manager.set(temp, temp2);
+                }
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(temp2);
+        }
 #else
-		mpz temp = m_tracker.get_random(fd->get_range());
+        mpz temp = m_tracker.get_random(fd->get_range());
 #endif
 
 #if _REAL_RS_ || _REAL_PBFS_
-		serious_update(fd, temp);
+        serious_update(fd, temp);
 #else
-		update(fd, temp);
+        update(fd, temp);
 #endif
         m_mpz_manager.del(temp);
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index a08588a51..553acc35a 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -125,10 +125,10 @@ Notes:
 
 
 #if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
-	InvalidConfiguration;
+    InvalidConfiguration;
 #endif
 #if (_PROBABILISTIC_UCT_ && !_UCT_)
-	InvalidConfiguration;
+    InvalidConfiguration;
 #endif
 
 
@@ -150,10 +150,10 @@ class sls_tactic : public tactic {
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
-			m_umins(0),
-			m_mul2s(0),
-			m_mul3s(0),
-			m_div2s(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -183,8 +183,8 @@ class sls_tactic : public tactic {
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
-		ptr_vector<mpz> m_old_values;
-		
+        ptr_vector<mpz> m_old_values;
+        
         typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
 
         imp(ast_manager & m, params_ref const & p, stats & s) : 
@@ -267,18 +267,18 @@ class sls_tactic : public tactic {
             #else
             double top_sum = 0.0;
             unsigned sz = g->size();
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
                 top_sum += m_tracker.get_score(e);
             }
 
-			TRACE("sls_top", tout << "Score distribution:"; 
+            TRACE("sls_top", tout << "Score distribution:"; 
                                     for (unsigned i = 0; i < sz; i++)
                                         tout << " " << m_tracker.get_score(g->form(i));
                                     tout << " AVG: " << top_sum / (double) sz << std::endl; );
 
 #if _CACHE_TOP_SCORE_
-			m_tracker.set_top_sum(top_sum);
+            m_tracker.set_top_sum(top_sum);
 #endif
 
             return top_sum / (double) sz;
@@ -292,20 +292,20 @@ class sls_tactic : public tactic {
         }
 
         double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.serious_update(fd, new_value);
+            m_evaluator.serious_update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
         }
 
         double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-			m_evaluator.update(fd, new_value);
+            m_evaluator.update(fd, new_value);
             m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-			return (m_tracker.get_top_sum() / g->size());
+            return (m_tracker.get_top_sum() / g->size());
 #else
             return top_score(g);
 #endif
@@ -314,18 +314,18 @@ class sls_tactic : public tactic {
 #if _EARLY_PRUNE_
         double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
             m_stats.m_incr_evals++;
-			if (m_evaluator.update_prune(fd, new_value))
+            if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-				return (m_tracker.get_top_sum() / g->size());
+                return (m_tracker.get_top_sum() / g->size());
 #else
-	            return top_score(g);
+                return top_score(g);
 #endif
-			else
-				return 0.0;
+            else
+                return 0.0;
         }
 #endif
 
-		// checks whether the score outcome of a given move is better than the previous score
+        // checks whether the score outcome of a given move is better than the previous score
         bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
 
@@ -357,11 +357,11 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// same as what_if, but only applied to the score of a specific atom, not the total score
+        // same as what_if, but only applied to the score of a specific atom, not the total score
         bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
                         double & best_score, unsigned & best_const, mpz & best_value) {
             m_evaluator.update(fd, temp);
-			double r = m_tracker.get_score(e);
+            double r = m_tracker.get_score(e);
             if (r >= best_score) {
                 best_score = r;
                 best_const = fd_inx;            
@@ -378,29 +378,29 @@ class sls_tactic : public tactic {
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
 
-		}
+        }
 
-		// Andreas: do we really need all those temporary mpzs?
-		void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+        // Andreas: do we really need all those temporary mpzs?
+        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             mpz temp, mask, mask2;
             m_mpz_manager.mul(old_value, m_two, temp);
             m_mpz_manager.set(mask, m_powers(bv_sz));
             m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
             m_mpz_manager.bitwise_and(temp, mask2, result);
-			m_mpz_manager.del(temp);
-			m_mpz_manager.del(mask);
-			m_mpz_manager.del(mask2);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
         }
 
         void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
             m_mpz_manager.div(old_value, m_two, result);
         }
 
-		void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
             unsigned shift;        
             m_mpz_manager.add(old_value, m_one, incremented);
             if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
@@ -437,73 +437,73 @@ class sls_tactic : public tactic {
 
         void mk_random_move(goal_ref const & g) {
             unsigned rnd_mv = 0;
-			if (m_stats.m_moves > 10000)
-				rnd_mv = 0;
+            if (m_stats.m_moves > 10000)
+                rnd_mv = 0;
 
-			ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
+            ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
 
-			mpz new_value;
+            mpz new_value;
 
-			sort * srt = fd->get_range();
+            sort * srt = fd->get_range();
             if (m_manager.is_bool(srt))
-				m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-			else
-			{
+                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+            else
+            {
 #if _USE_ADDSUB_
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-	            if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-				move_type mt = (move_type) rnd_mv;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+                move_type mt = (move_type) rnd_mv;
 
-				// inversion doesn't make sense, let's do a flip instead.
-				if (mt == MV_INV) mt = MV_FLIP;
+                // inversion doesn't make sense, let's do a flip instead.
+                if (mt == MV_INV) mt = MV_FLIP;
 #else
-				mt = MV_FLIP;
+                mt = MV_FLIP;
 #endif
-				unsigned bit = 0;
+                unsigned bit = 0;
 
-				switch (mt)
-				{
-					case MV_FLIP: {
-					unsigned bv_sz = m_bv_util.get_bv_size(srt);
-					bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-					mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-					break;
-				}
-				case MV_INC: 
-					mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_DEC: 
-					mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				case MV_INV:
-					mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-					break;
-				default:
-					NOT_IMPLEMENTED_YET();
-				}
+                switch (mt)
+                {
+                    case MV_FLIP: {
+                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
+                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+                    break;
+                }
+                case MV_INC: 
+                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_DEC: 
+                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_INV:
+                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                default:
+                    NOT_IMPLEMENTED_YET();
+                }
 
-				TRACE("sls", tout << "Randomization candidates: ";
-							 for (unsigned i = 0; i < unsat_constants.size(); i++)
-								 tout << unsat_constants[i]->get_name() << ", ";
-							 tout << std::endl;
-							 tout << "Random move: ";
-							 switch (mt) {
-							 case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-							 case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-							 case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-							 case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-							 }
-							 tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-			}
+                TRACE("sls", tout << "Randomization candidates: ";
+                             for (unsigned i = 0; i < unsat_constants.size(); i++)
+                                 tout << unsat_constants[i]->get_name() << ", ";
+                             tout << std::endl;
+                             tout << "Random move: ";
+                             switch (mt) {
+                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+                             }
+                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+            }
 
-			m_evaluator.update(fd, new_value);            
-			m_mpz_manager.del(new_value);
-		}
+            m_evaluator.update(fd, new_value);            
+            m_mpz_manager.del(new_value);
+        }
 
-		// will use VNS to ignore some possible moves and increase the flips per second
+        // will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
@@ -514,7 +514,7 @@ class sls_tactic : public tactic {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
                 bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-				if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -536,12 +536,12 @@ class sls_tactic : public tactic {
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                         move = MV_INV;
 
-					// try to flip lsb
-					mk_flip(srt, old_value, 0, temp);                
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = 0;
-	                    move = MV_FLIP;
-					}
+                    // try to flip lsb
+                    mk_flip(srt, old_value, 0, temp);                
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = 0;
+                        move = MV_FLIP;
+                    }
                 }
 
                 // reset to what it was before
@@ -549,12 +549,12 @@ class sls_tactic : public tactic {
                 SASSERT(check == score);
             }
 
-			// we can either check the condition once in the beginning or check it repeatedly after every bit
+            // we can either check the condition once in the beginning or check it repeatedly after every bit
 #if _VNS_ == 1
-			for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
 #else
-			if (new_score <= score)
-			for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+            if (new_score <= score)
+            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
 #endif
             for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
                 func_decl * fd = to_evaluate[i];
@@ -563,30 +563,30 @@ class sls_tactic : public tactic {
                 m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
                 // What would happen if we flipped bit #j ?                
-				if (j < bv_sz)
-				{
-					mk_flip(srt, old_value, j, temp);                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);                
 
-	                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-	                    new_bit = j;
-	                    move = MV_FLIP;
-	                }
-				}
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
                 SASSERT(check == score);
             }
-			m_mpz_manager.del(old_value);
+            m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
             return new_score;
         }        
 
-		// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
         double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
-			mpz temp2;
+            mpz temp2;
 #endif
             unsigned bv_sz;
             double new_score = score;
@@ -599,11 +599,11 @@ class sls_tactic : public tactic {
 
                 // first try to flip every bit
 #if _SKIP_BITS_
-				for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
 #else
-				for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
 #endif
-					// What would happen if we flipped bit #i ?                
+                    // What would happen if we flipped bit #i ?                
                     mk_flip(srt, old_value, j, temp);                
 
                     if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
@@ -614,7 +614,7 @@ class sls_tactic : public tactic {
 
                 if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
 #if _USE_ADDSUB_
-					if (!m_mpz_manager.is_even(old_value)) { 
+                    if (!m_mpz_manager.is_even(old_value)) { 
                         // for odd values, try +1
                         mk_inc(bv_sz, old_value, temp);
                         if (what_if(g, fd, i, temp, new_score, best_const, best_value))
@@ -660,7 +660,7 @@ class sls_tactic : public tactic {
 
                 // reset to what it was before
                 double check = incremental_score(g, fd, old_value);
-				// Andreas: does not hold anymore now that we use top level score caching
+                // Andreas: does not hold anymore now that we use top level score caching
                 //SASSERT(check == score);
             }
 
@@ -669,17 +669,17 @@ class sls_tactic : public tactic {
 #if _USE_MUL3_
             m_mpz_manager.del(temp2);
 #endif
-			return new_score;
+            return new_score;
         }        
 
-		// same as find_best_move but only considers the score of the current expression instead of the overall score
-		double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+        // same as find_best_move but only considers the score of the current expression instead of the overall score
+        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
             mpz old_value, temp;
             unsigned bv_sz;
-			double new_score = m_tracker.get_score(e);
-			// Andreas: tie breaking not implemented yet
-			// double tie_score = top_score(g);
+            double new_score = m_tracker.get_score(e);
+            // Andreas: tie breaking not implemented yet
+            // double tie_score = top_score(g);
             for (unsigned i = 0; i < to_evaluate.size(); i++) {
                 func_decl * fd = to_evaluate[i];
                 sort * srt = fd->get_range();
@@ -718,7 +718,7 @@ class sls_tactic : public tactic {
                 }
 
                 // reset to what it was before
-	            m_evaluator.update(fd, old_value);
+                m_evaluator.update(fd, old_value);
             }
 
             m_mpz_manager.del(old_value);
@@ -726,37 +726,37 @@ class sls_tactic : public tactic {
             return new_score;
         }        
 
-		// first try of intensification ... does not seem to be efficient
-		bool handle_plateau(goal_ref const & g)
-		{
-			unsigned sz = g->size();
+        // first try of intensification ... does not seem to be efficient
+        bool handle_plateau(goal_ref const & g)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned pos = m_stats.m_moves % sz;
+            unsigned pos = m_stats.m_moves % sz;
 #else
-			unsigned pos = m_tracker.get_random_uint(16) % sz;
+            unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-			{
-				m_tracker.get_value(to_evaluate[i]);
-				m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-			}            
-			unsigned new_const = (unsigned)-1, new_bit = 0;        
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+            {
+                m_tracker.get_value(to_evaluate[i]);
+                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+            }            
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
             mpz new_value;
             move_type move;
-			for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-			{
-				// Andreas: Could be extended to use (best) score but this is computationally more expensive.
+            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+            {
+                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
                 find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
 
                 if (new_const == static_cast<unsigned>(-1)) {
-					// Andreas: Actually this should never happen.
-					NOT_IMPLEMENTED_YET();
+                    // Andreas: Actually this should never happen.
+                    NOT_IMPLEMENTED_YET();
                 } else {
                     m_stats.m_moves++;
                     func_decl * fd = to_evaluate[new_const];
@@ -767,35 +767,35 @@ class sls_tactic : public tactic {
                     case MV_DEC: m_stats.m_decs++; break;
                     case MV_INV: m_stats.m_invs++; break;
                     case MV_UMIN: m_stats.m_umins++; break;
-					case MV_MUL2: m_stats.m_mul2s++; break;
-					case MV_MUL3: m_stats.m_mul3s++; break;
-					case MV_DIV2: m_stats.m_div2s++; break;
+                    case MV_MUL2: m_stats.m_mul2s++; break;
+                    case MV_MUL3: m_stats.m_mul3s++; break;
+                    case MV_DIV2: m_stats.m_div2s++; break;
                     }
                     
-					m_evaluator.update(fd, new_value);
+                    m_evaluator.update(fd, new_value);
                 }
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			for (unsigned i = 0; i < to_evaluate.size(); i++)
-				m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
 
-			m_old_values.reset();
+            m_old_values.reset();
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// what_if version needed in the context of 2nd intensification try, combining local and global score
+        // what_if version needed in the context of 2nd intensification try, combining local and global score
         bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
                         double & best_score, mpz & best_value, unsigned i) {
         
             double global_score = incremental_score(g, fd, temp);
-			double local_score = m_tracker.get_score(e);
+            double local_score = m_tracker.get_score(e);
             double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
-			if (new_score >= best_score) {
+            if (new_score >= best_score) {
                 best_score = new_score;
                 m_mpz_manager.set(best_value, temp);
                 return true;
@@ -804,17 +804,17 @@ class sls_tactic : public tactic {
             return false;
         }
 
-		// find_best_move version needed in the context of 2nd intensification try
+        // find_best_move version needed in the context of 2nd intensification try
         double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-		{
-			mpz old_value, temp;
+        {
+            mpz old_value, temp;
             double best_score = 0;
 
             sort * srt = fd->get_range();
             unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
             m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
-			for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
                 mk_flip(srt, old_value, j, temp);                
                 what_if(g, e, fd, temp, best_score, best_value, i); 
             }
@@ -822,54 +822,54 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(old_value);
             m_mpz_manager.del(temp);
 
-			return best_score;
+            return best_score;
         }        
 
-		// second try to use intensification ... also not very effective
-		bool handle_plateau(goal_ref const & g, double old_score)
-		{
-			unsigned sz = g->size();
+        // second try to use intensification ... also not very effective
+        bool handle_plateau(goal_ref const & g, double old_score)
+        {
+            unsigned sz = g->size();
 #if _BFS_
-			unsigned new_const = m_stats.m_moves % sz;
+            unsigned new_const = m_stats.m_moves % sz;
 #else
-			unsigned new_const = m_tracker.get_random_uint(16) % sz;
+            unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-			expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-	        if (!e)
-				return 0;
+            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+            if (!e)
+                return 0;
 
-			expr * q = m_tracker.get_unsat_expression(e);
-			ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
 
-			new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-			func_decl * fd = to_evaluate[new_const];
+            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+            func_decl * fd = to_evaluate[new_const];
 
-			mpz new_value;
-			//m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-			unsigned new_bit = 0;        
-			double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-			
-			for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-			{
+            mpz new_value;
+            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+            unsigned new_bit = 0;        
+            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+            
+            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+            {
                 new_score = find_best_move_local(g, q, fd, new_value, i);
 
                 m_stats.m_moves++;
                 m_stats.m_flips++;
 
-				global_score = incremental_score(g, fd, new_value);
-     			local_score = m_tracker.get_score(q);
+                global_score = incremental_score(g, fd, new_value);
+                 local_score = m_tracker.get_score(q);
 
-				SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
 
-				if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-					return 1;
-			}
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
 
-			return 0;
-		}
+            return 0;
+        }
 
-		// main search loop
-		lbool search(goal_ref const & g) {        
+        // main search loop
+        lbool search(goal_ref const & g) {        
             lbool res = l_undef;
             double score = 0.0, old_score = 0.0;
             unsigned new_const = (unsigned)-1, new_bit = 0;        
@@ -885,52 +885,52 @@ class sls_tactic : public tactic {
         
             unsigned plateau_cnt = 0;
 
-			// Andreas: Why do we only allow so few plateaus?
+            // Andreas: Why do we only allow so few plateaus?
 #if _RESTARTS_
-			while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+            while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
-					if (m_stats.m_moves == 5590)
+                    if (m_stats.m_moves == 5590)
                     checkpoint();
 
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
 #endif
             
 #if _TYPE_RSTEP_
-					if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-					{
+                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                    {
 #if _TYPE_RSTEP_ == 1
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #elif _TYPE_RSTEP_ == 2
-						mk_random_move(g);
+                        mk_random_move(g);
 #endif
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
-							} else
-								TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-						}
-					}
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                            } else
+                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                        }
+                    }
 #endif
                     old_score = score;
                     new_const = (unsigned)-1;
                         
-					ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-					if (!to_evaluate.size())
-					{
-						res = l_true;
-						goto bailout;
-					}
+                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+                    if (!to_evaluate.size())
+                    {
+                        res = l_true;
+                        goto bailout;
+                    }
                     TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
                                             for (unsigned i = 0 ; i < to_evaluate.size(); i++)
                                                 tout << to_evaluate[i]->get_name() << std::endl; );
@@ -952,11 +952,11 @@ class sls_tactic : public tactic {
                                         for (unsigned i = 0; i < g->size(); i++)
                                             tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
                                             m_tracker.get_score(g->form(i)) << std::endl; );
-						// Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                         score = old_score;
                     }
                     else {
-						// Andreas: Why does randomizing not count as a move? (Now it does.)
+                        // Andreas: Why does randomizing not count as a move? (Now it does.)
                         m_stats.m_moves++;
                         func_decl * fd = to_evaluate[new_const];
 
@@ -984,15 +984,15 @@ class sls_tactic : public tactic {
                         case MV_DEC: m_stats.m_decs++; break;
                         case MV_INV: m_stats.m_invs++; break;
                         case MV_UMIN: m_stats.m_umins++; break;
-						case MV_MUL2: m_stats.m_mul2s++; break;
-						case MV_MUL3: m_stats.m_mul3s++; break;
-						case MV_DIV2: m_stats.m_div2s++; break;
+                        case MV_MUL2: m_stats.m_mul2s++; break;
+                        case MV_MUL3: m_stats.m_mul3s++; break;
+                        case MV_DIV2: m_stats.m_div2s++; break;
                         }
                     
 #if _REAL_RS_ || _REAL_PBFS_
-						score = serious_score(g, fd, new_value);
+                        score = serious_score(g, fd, new_value);
 #else
-						score = incremental_score(g, fd, new_value);    
+                        score = incremental_score(g, fd, new_value);    
 #endif
 
                         TRACE("sls", tout << "Score distribution:"; 
@@ -1004,7 +1004,7 @@ class sls_tactic : public tactic {
                     if (score >= 0.99999) {
 //                    if (score >= 1.0) {
                         // score could theoretically be imprecise.
-						// Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                         bool all_true = true;
                         for (unsigned i = 0; i < g->size() && all_true; i++)
                             if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
@@ -1015,43 +1015,43 @@ class sls_tactic : public tactic {
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
-					/*
-					if (m_stats.m_moves % 100 == 0)
-					{
-						verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-						verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-					}*/
+                    /*
+                    if (m_stats.m_moves % 100 == 0)
+                    {
+                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+                    }*/
                 }
                 while (score > old_score && res == l_undef);                
-				
-				// Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                
+                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
                 if (score != old_score) {
-					report_tactic_progress("This should not happen I guess.", plateau_cnt);
+                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
                     plateau_cnt = 0;
-				} else {
-					m_stats.m_moves++;
+                } else {
+                    m_stats.m_moves++;
                     plateau_cnt++;
-					//report_tactic_progress("Plateau.", plateau_cnt);
-					// Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //report_tactic_progress("Plateau.", plateau_cnt);
+                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
                     //if (plateau_cnt < m_plateau_limit) {
                         TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
 #if _INTENSIFICATION_
-						handle_plateau(g, score);
-						//handle_plateau(g);
+                        handle_plateau(g, score);
+                        //handle_plateau(g);
 #else
-						m_evaluator.randomize_local(g, m_stats.m_moves);
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
 #endif
-						//mk_random_move(g);
+                        //mk_random_move(g);
                         score = top_score(g);
 
-	                    if (score >= 1.0) {
-	                        bool all_true = true;
-	                        for (unsigned i = 0; i < g->size() && all_true; i++)
-	                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-	                                all_true=false;
-	                        if (all_true) {
-	                            res = l_true; // sat
-	                            goto bailout;
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
                         } else
                             TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
                     }
@@ -1070,43 +1070,43 @@ class sls_tactic : public tactic {
                 return;
             }
 
-			verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-			verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-			verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-			verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-			verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-			verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-			verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-			verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-			verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-			verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-			verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-			verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-			verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-			verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-			verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-			verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-			verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-			verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-			verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-			verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-			verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-			verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-			verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-			verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-			verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-			
+            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+            
 #if _WEIGHT_DIST_ == 4
-					m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
 #endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
             do {
                 checkpoint();
-				// Andreas: I think restarts are too impotant to ignore 99% of them are happening...
+                // Andreas: I think restarts are too impotant to ignore 99% of them are happening...
                 //if ((m_stats.m_restarts % 100) == 0)                        
                     report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 
@@ -1115,12 +1115,12 @@ class sls_tactic : public tactic {
                 if (res == l_undef)
                     m_tracker.randomize();
             }
-			while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
-			verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
 
             if (res == l_true) {    
-				report_tactic_progress("Number of flips:", m_stats.m_moves);
+                report_tactic_progress("Number of flips:", m_stats.m_moves);
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -1254,7 +1254,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-						// Andreas: How does a NNF actually look like? Can it contain ITE operators?
+                        // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index b26912e5c..006bbb888 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -29,31 +29,31 @@ class sls_tracker {
     unsigned              m_random_bits;
     unsigned              m_random_bits_cnt;
     mpz                   m_zero, m_one, m_two;
-	    
+        
     struct value_score { 
 #if _EARLY_PRUNE_
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
 #else
-		value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
 #endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
         double score;
 #if _EARLY_PRUNE_
-		double score_prune;
-		unsigned has_pos_occ;
-		unsigned has_neg_occ;
+        double score_prune;
+        unsigned has_pos_occ;
+        unsigned has_neg_occ;
 #endif
         unsigned distance; // max distance from any root
-		unsigned touched;
+        unsigned touched;
         value_score & operator=(const value_score & other) {
             SASSERT(m == 0 || m == other.m);
             if (m) m->set(value, 0); else m = other.m;
             m->set(value, other.value);
             score = other.score;
             distance = other.distance;
-			touched = other.touched;
+            touched = other.touched;
             return *this;
         }
     };
@@ -72,18 +72,18 @@ private:
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
 #if _UCT_
-	unsigned              m_touched;
+    unsigned              m_touched;
 #endif
 #if _REAL_RS_ || _REAL_PBFS_
-	ptr_vector<expr>	  m_unsat_expr;
-	obj_map<expr, unsigned>	m_where_false;
-	expr**					m_list_false;
+    ptr_vector<expr>      m_unsat_expr;
+    obj_map<expr, unsigned>    m_where_false;
+    expr**                    m_list_false;
 #endif
 #if _CACHE_TOP_SCORE_
-	double				  m_top_sum;
+    double                  m_top_sum;
 #endif
 #if _WEIGHT_DIST_ == 4
-	double				  m_weight_dist_factor;
+    double                  m_weight_dist_factor;
 #endif
 
 public:    
@@ -105,23 +105,23 @@ public:
     }
 
 #if _WEIGHT_DIST_ == 4
-	inline void set_weight_dist_factor(double val) {
-		m_weight_dist_factor = val;
-	}
+    inline void set_weight_dist_factor(double val) {
+        m_weight_dist_factor = val;
+    }
 #endif
 
 #if _CACHE_TOP_SCORE_
-	inline void adapt_top_sum(double add, double sub) {
-		m_top_sum += add - sub;
-	}
+    inline void adapt_top_sum(double add, double sub) {
+        m_top_sum += add - sub;
+    }
 
-	inline void set_top_sum(double new_score) {
-		m_top_sum = new_score;
-	}
+    inline void set_top_sum(double new_score) {
+        m_top_sum = new_score;
+    }
 
-	inline double get_top_sum() {
-		return m_top_sum;
-	}
+    inline double get_top_sum() {
+        return m_top_sum;
+    }
 #endif
 
     inline void set_value(expr * n, const mpz & r) {
@@ -174,20 +174,20 @@ public:
         m_scores.find(n).score_prune = score;
     }
 
-	inline double & get_score_prune(expr * n) {
+    inline double & get_score_prune(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).score_prune;
     }
 
-	inline unsigned has_pos_occ(expr * n) {
+    inline unsigned has_pos_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_pos_occ;
- 	}
+     }
 
-	inline unsigned has_neg_occ(expr * n) {
+    inline unsigned has_neg_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
- 	}
+     }
 #endif
 
     inline unsigned get_distance(expr * n) {
@@ -316,45 +316,45 @@ public:
         }
     }
 
-	void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(proc, visited, q);
-			}
-		}
-		for_each_expr(proc, visited, e);
- 	}
+    void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(proc, visited, q);
+            }
+        }
+        for_each_expr(proc, visited, e);
+     }
 
-	void initialize_recursive(expr * e) {
-		if (m_manager.is_and(e) || m_manager.is_or(e)) {
-			app * a = to_app(e);
-			expr * const * args = a->get_args();
-			unsigned int sz = a->get_num_args();
-			for (unsigned int i = 0; i < sz; i++) {
-		        expr * q = args[i];
-				initialize_recursive(q);
-			}
-		}
-		ptr_vector<func_decl> t;
+    void initialize_recursive(expr * e) {
+        if (m_manager.is_and(e) || m_manager.is_or(e)) {
+            app * a = to_app(e);
+            expr * const * args = a->get_args();
+            unsigned int sz = a->get_num_args();
+            for (unsigned int i = 0; i < sz; i++) {
+                expr * q = args[i];
+                initialize_recursive(q);
+            }
+        }
+        ptr_vector<func_decl> t;
         m_constants_occ.insert_if_not_there(e, t);
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
- 	}
+     }
 
-	void initialize(goal_ref const & g) {
+    void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2
-			initialize_recursive(proc, visited, e);
+            initialize_recursive(proc, visited, e);
 #endif
             for_each_expr(proc, visited, e);
         }
@@ -363,9 +363,9 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
-			// Andreas: Maybe not fully correct.
+            // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
-			initialize_recursive(e);
+            initialize_recursive(e);
 #endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
@@ -379,53 +379,53 @@ public:
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
 #if _REAL_RS_ || _REAL_PBFS_
-		m_list_false = new expr*[sz];
+        m_list_false = new expr*[sz];
         for (unsigned i = 0; i < sz; i++)
-	  		if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-				break_assertion(g->form(i));
+              if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+                break_assertion(g->form(i));
 #endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-	  		setup_occs(g->form(i));
+              setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-		m_touched = 1;
+        m_touched = 1;
 #endif
     }
 
 #if _REAL_RS_ || _REAL_PBFS_
-	void make_assertion(expr * e)
-	{
-		if (m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.find(e);
-			m_where_false.erase(e);
-			if (pos != m_where_false.size())
-			{
-				expr * q = m_list_false[m_where_false.size()];
-				m_list_false[pos] = q;
-				m_where_false.find(q) = pos;
-			}
-//			printf("Going in %d\n", m_where_false.size());
-		}
-		//if (m_unsat_expr.contains(e))
-			//m_unsat_expr.erase(e);
-	}
+    void make_assertion(expr * e)
+    {
+        if (m_where_false.contains(e))
+        {
+            unsigned pos = m_where_false.find(e);
+            m_where_false.erase(e);
+            if (pos != m_where_false.size())
+            {
+                expr * q = m_list_false[m_where_false.size()];
+                m_list_false[pos] = q;
+                m_where_false.find(q) = pos;
+            }
+//            printf("Going in %d\n", m_where_false.size());
+        }
+        //if (m_unsat_expr.contains(e))
+            //m_unsat_expr.erase(e);
+    }
 
-	void break_assertion(expr * e)
-	{
-		if (!m_where_false.contains(e))
-		{
-			unsigned pos = m_where_false.size();
-			m_list_false[pos] = e;
-			m_where_false.insert(e, pos);
-	//		printf("Going in %d\n", m_where_false.size());
-		}
-		//if (!m_unsat_expr.contains(e))
-			//m_unsat_expr.push_back(e);
-	}
+    void break_assertion(expr * e)
+    {
+        if (!m_where_false.contains(e))
+        {
+            unsigned pos = m_where_false.size();
+            m_list_false[pos] = e;
+            m_where_false.insert(e, pos);
+    //        printf("Going in %d\n", m_where_false.size());
+        }
+        //if (!m_unsat_expr.contains(e))
+            //m_unsat_expr.push_back(e);
+    }
 #endif
 
     void show_model(std::ostream & out) {
@@ -537,35 +537,35 @@ public:
     }              
 
 #if _EARLY_PRUNE_
-	void setup_occs(expr * n, bool negated = false) {
-		if (m_manager.is_bool(n))
-		{
-			if (m_manager.is_and(n) || m_manager.is_or(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            expr * const * args = a->get_args();
-	            for (unsigned i = 0; i < a->get_num_args(); i++)
-					setup_occs(args[i]);
-			}
-			else if (m_manager.is_not(n))
-			{
-	            SASSERT(!negated);
-	            app * a = to_app(n);
-	            SASSERT(a->get_num_args() == 1);
-	            expr * child = a->get_arg(0);
-	            if (m_manager.is_and(child) || m_manager.is_or(child))
-	                NOT_IMPLEMENTED_YET();
-				setup_occs(child, true);
-			}
-			else
-			{
-				if (negated)
-					m_scores.find(n).has_neg_occ = 1;
-				else
-					m_scores.find(n).has_pos_occ = 1;
-			}
-		}
+    void setup_occs(expr * n, bool negated = false) {
+        if (m_manager.is_bool(n))
+        {
+            if (m_manager.is_and(n) || m_manager.is_or(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                expr * const * args = a->get_args();
+                for (unsigned i = 0; i < a->get_num_args(); i++)
+                    setup_occs(args[i]);
+            }
+            else if (m_manager.is_not(n))
+            {
+                SASSERT(!negated);
+                app * a = to_app(n);
+                SASSERT(a->get_num_args() == 1);
+                expr * child = a->get_arg(0);
+                if (m_manager.is_and(child) || m_manager.is_or(child))
+                    NOT_IMPLEMENTED_YET();
+                setup_occs(child, true);
+            }
+            else
+            {
+                if (negated)
+                    m_scores.find(n).has_neg_occ = 1;
+                else
+                    m_scores.find(n).has_pos_occ = 1;
+            }
+        }
         else
             NOT_IMPLEMENTED_YET();
     }
@@ -574,7 +574,7 @@ public:
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
 
-		double res = 0.0;
+        double res = 0.0;
             
         if (is_uninterp_const(n)) {
             const mpz & r = get_value(n);
@@ -587,14 +587,14 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it does not even occur.
+            // Andreas: Seems to have no effect. Probably it does not even occur.
 #if _SCORE_AND_AVG_
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
                 sum += get_score(args[i]);
             res = sum / (double) a->get_num_args();
 #else
-			double min = 1.0;
+            double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur < min) min = cur;
@@ -606,16 +606,16 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-			// Andreas: Seems to have no effect. Probably it is still too similar to the original version.
+            // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
 #if _SCORE_OR_MUL_
-			double inv = 1.0;
+            double inv = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 inv *= (1.0 - get_score(args[i]));
             }
             res = 1.0 - inv;
 #else
-			double max = 0.0;
+            double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
                 if (cur > max) max = cur;
@@ -639,7 +639,7 @@ public:
             expr * arg1 = a->get_arg(1);
             const mpz & v0 = get_value(arg0);
             const mpz & v1 = get_value(arg1);
-			
+            
             if (negated) {                    
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
@@ -701,7 +701,7 @@ public:
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
                     res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-					m_mpz_manager.del(diff);
+                    m_mpz_manager.del(diff);
                 }
             }
             else {
@@ -762,7 +762,7 @@ public:
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
-			m_mpz_manager.del(x);
+            m_mpz_manager.del(x);
             m_mpz_manager.del(y);                
         }
         else if (m_manager.is_not(n)) {                
@@ -797,25 +797,25 @@ public:
         SASSERT(res >= 0.0 && res <= 1.0);
 
 #if _WEIGHT_DIST_
-		app * a = to_app(n);
-		family_id afid = a->get_family_id();
+        app * a = to_app(n);
+        family_id afid = a->get_family_id();
 
-		if (afid == m_bv_util.get_family_id())
+        if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
-		if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+        if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
 #elif _WEIGHT_DIST_ == 2
-		res *= res;
+        res *= res;
 #elif _WEIGHT_DIST_ == 3
-		if (res < 1.0) res = 0.0;
+        if (res < 1.0) res = 0.0;
 #elif _WEIGHT_DIST_ == 4
-		if (res < 1.0) res *= m_weight_dist_factor;
+        if (res < 1.0) res *= m_weight_dist_factor;
 #endif
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
     }
-	
+    
     double score_bv(expr * n) {
         return 0.0; // a bv-expr is always scored as 0.0; we won't use those scores.
     }
@@ -861,34 +861,34 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-	expr * get_unsat_expression(expr * e) {
-		if (m_manager.is_bool(e)) {
-			if (m_manager.is_and(e) || m_manager.is_or(e)) {
-				app * a = to_app(e);
-				expr * const * args = a->get_args();
-			    // Andreas: might be used for guided branching
-				//for (unsigned i = 0; i < a->get_num_args(); i++) {
-					//double cur = get_score(args[i]);
-				//}
-				// Andreas: A random number is better here since reusing flip will cause patterns.
-				unsigned int sz = a->get_num_args();
-				unsigned int pos = get_random_uint(16) % sz;
-				for (unsigned int i = pos; i < sz; i++) {
-	                expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-				}
-				for (unsigned int i = 0; i < pos; i++) {
-					expr * q = args[i];
-	                if (m_mpz_manager.neq(get_value(q), m_one))
-			            return get_unsat_expression(q);
-	            }
-	        }
-		}
-		return e;
-	}
+    expr * get_unsat_expression(expr * e) {
+        if (m_manager.is_bool(e)) {
+            if (m_manager.is_and(e) || m_manager.is_or(e)) {
+                app * a = to_app(e);
+                expr * const * args = a->get_args();
+                // Andreas: might be used for guided branching
+                //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                    //double cur = get_score(args[i]);
+                //}
+                // Andreas: A random number is better here since reusing flip will cause patterns.
+                unsigned int sz = a->get_num_args();
+                unsigned int pos = get_random_uint(16) % sz;
+                for (unsigned int i = pos; i < sz; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+                for (unsigned int i = 0; i < pos; i++) {
+                    expr * q = args[i];
+                    if (m_mpz_manager.neq(get_value(q), m_one))
+                        return get_unsat_expression(q);
+                }
+            }
+        }
+        return e;
+    }
 
-	ptr_vector<func_decl> & get_constants(expr * e) {
+    ptr_vector<func_decl> & get_constants(expr * e) {
         ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
         unsigned sz = this_decls.size();
         for (unsigned i = 0; i < sz; i++) {
@@ -897,9 +897,9 @@ public:
                 m_temp_constants.push_back(fd);
         }
         return m_temp_constants;
-	}
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
@@ -913,244 +913,244 @@ public:
             }
         }
         return m_temp_constants;
-	}
+    }
 
-	expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
-			for (unsigned i = pos; i < sz; i++) {
+    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+            for (unsigned i = pos; i < sz; i++) {
                 expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
-			}
-			for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-		            return q;
+                    return q;
             }
-			return 0;
-	}
+            for (unsigned i = 0; i < pos; i++) {
+                expr * q = g->form(i);
+                if (m_mpz_manager.neq(get_value(q), m_one))
+                    return q;
+            }
+            return 0;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-			expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(g, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
-			if (!q)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
+            if (!q)
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
-			if (!e)
-				return m_temp_constants;
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
+            if (!e)
+                return m_temp_constants;
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz = this_decls.size();
             for (unsigned j = 0; j < sz; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & go_deeper(expr * e) {
-			if (m_manager.is_bool(e)) {
-				if (m_manager.is_and(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-				    // Andreas: might be used for guided branching
-					//for (unsigned i = 0; i < a->get_num_args(); i++) {
-						//double cur = get_score(args[i]);
-					//}
-					// Andreas: A random number is better here since reusing flip will cause patterns.
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-				else if (m_manager.is_or(e)) {
-					app * a = to_app(e);
-					expr * const * args = a->get_args();
-					unsigned int sz = a->get_num_args();
-					unsigned int pos = get_random_uint(16) % sz;
-					for (unsigned int i = pos; i < sz; i++) {
-		                expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-					}
-					for (unsigned int i = 0; i < pos; i++) {
-						expr * q = args[i];
-		                if (m_mpz_manager.neq(get_value(q), m_one))
-				            return go_deeper(q);
-		            }
-		        }
-			}
-			ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+    ptr_vector<func_decl> & go_deeper(expr * e) {
+            if (m_manager.is_bool(e)) {
+                if (m_manager.is_and(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    // Andreas: might be used for guided branching
+                    //for (unsigned i = 0; i < a->get_num_args(); i++) {
+                        //double cur = get_score(args[i]);
+                    //}
+                    // Andreas: A random number is better here since reusing flip will cause patterns.
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+                else if (m_manager.is_or(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    unsigned int pos = get_random_uint(16) % sz;
+                    for (unsigned int i = pos; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                    for (unsigned int i = 0; i < pos; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one))
+                            return go_deeper(q);
+                    }
+                }
+            }
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz2 = this_decls.size();
             for (unsigned j = 0; j < sz2; j++) {
                 func_decl * fd = this_decls[j];
                 if (!m_temp_constants.contains(fd))
                     m_temp_constants.push_back(fd);
             }
-	        return m_temp_constants;
-	}
+            return m_temp_constants;
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-		expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(g, sz, pos);
         if (!q)
-			return m_temp_constants;
+            return m_temp_constants;
 
-		return go_deeper(q);
-	}
+        return go_deeper(q);
+    }
 
-	ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
         unsigned sz = g->size();
 
         if (sz == 1) {
-			if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
-				return m_temp_constants;
-			else
-	            return get_constants();
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+                return m_temp_constants;
+            else
+                return get_constants();
         }
         else {
             m_temp_constants.reset();
 #if _FOCUS_ == 1
 #if _UCT_
-			unsigned pos = -1;
-			value_score vscore;
+            unsigned pos = -1;
+            value_score vscore;
 #if _PROBABILISTIC_UCT_
-			double sum_score = 0.0;
-			unsigned start_index = get_random_uint(16) % sz;
-			for (unsigned i = start_index; i < sz; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+            double sum_score = 0.0;
+            unsigned start_index = get_random_uint(16) % sz;
+            for (unsigned i = start_index; i < sz; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
-			for (unsigned i = 0; i < start_index; i++)
-			{
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }    
+            }
+            for (unsigned i = 0; i < start_index; i++)
+            {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-					sum_score += q;
-					if (rand() <= (q * RAND_MAX / sum_score) + 1)
-						pos = i;
-				}	
-			}
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                    sum_score += q;
+                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                        pos = i;
+                }    
+            }
 #else
-			double max = -1.0;
-			for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
-				vscore = m_scores.find(e);
+            double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+                vscore = m_scores.find(e);
 #if _UCT_ == 1
-				double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
 #elif _UCT_ == 2
-				double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+                double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
 #endif
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
 
 #if _UCT_ == 1
-			m_scores.find(g->form(pos)).touched++;
-			m_touched++;
+            m_scores.find(g->form(pos)).touched++;
+            m_touched++;
 #elif _UCT_ == 2
-			m_scores.find(g->form(pos)).touched = flip; 
+            m_scores.find(g->form(pos)).touched = flip; 
 #endif
-			expr * e = g->form(pos);
+            expr * e = g->form(pos);
 
 #elif _BFS_ == 3
-			unsigned int pos = -1;
-			double max = -1.0;
+            unsigned int pos = -1;
+            double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 2
-			unsigned int pos = -1;
-			double min = 2.0;
+            unsigned int pos = -1;
+            double min = 2.0;
             for (unsigned i = 0; i < sz; i++) {
-				expr * e = g->form(i);
+                expr * e = g->form(i);
                 double q = get_score(e);
-				if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+                if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
             }
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _BFS_ == 1
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #elif _UNIFORM_RANDOM_
-			unsigned cnt_unsat = 0, pos = -1;
-			for (unsigned i = 0; i < sz; i++)
-				if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-			if (pos == static_cast<unsigned>(-1))
-				return m_temp_constants;
-			expr * e = g->form(pos);
+            unsigned cnt_unsat = 0, pos = -1;
+            for (unsigned i = 0; i < sz; i++)
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;    
+            if (pos == static_cast<unsigned>(-1))
+                return m_temp_constants;
+            expr * e = g->form(pos);
 #elif _REAL_RS_
-			//unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[get_random_uint(16) % sz];
+            //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            else
+                expr * e = m_list_false[get_random_uint(16) % sz];
 #elif _REAL_PBFS_
-			//unsigned pos = m_false_list[flip % m_cnt_false];
-			//expr * e = get_unsat_assertion(g, sz, pos);
-			//expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-			sz = m_where_false.size();
-			if (sz == 0)
-				return m_temp_constants;
-			else
-				expr * e = m_list_false[flip % sz];
+            //unsigned pos = m_false_list[flip % m_cnt_false];
+            //expr * e = get_unsat_assertion(g, sz, pos);
+            //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+            sz = m_where_false.size();
+            if (sz == 0)
+                return m_temp_constants;
+            else
+                expr * e = m_list_false[flip % sz];
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
-			expr * e = get_unsat_assertion(g, sz, pos);
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
+            expr * e = get_unsat_assertion(g, sz, pos);
 #endif
-			return get_unsat_constants_walksat(e);
+            return get_unsat_constants_walksat(e);
 #elif _FOCUS_ == 2
 #if _BFS_
-			// I guess it was buggy ...
-			// unsigned int pos = flip % m_constants.size();
-			unsigned int pos = flip % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = flip % m_constants.size();
+            unsigned int pos = flip % sz;
 #else
-			// I guess it was buggy ...
-			// unsigned int pos = get_random_uint(16) % m_constants.size();
-			unsigned int pos = get_random_uint(16) % sz;
+            // I guess it was buggy ...
+            // unsigned int pos = get_random_uint(16) % m_constants.size();
+            unsigned int pos = get_random_uint(16) % sz;
 #endif
-			return get_unsat_constants_crsat(g, sz, pos);
+            return get_unsat_constants_crsat(g, sz, pos);
 #else
-			return get_unsat_constants_gsat(g, sz);
+            return get_unsat_constants_gsat(g, sz);
 #endif
         }
     }

From 442827e5236f2152b498f2cabe42a50d3b095a1c Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Wed, 19 Mar 2014 11:49:44 +0000
Subject: [PATCH 070/108] Current version for relocating.

---
 src/tactic/sls/sls_evaluator.h |  92 +++++-----
 src/tactic/sls/sls_tactic.cpp  | 295 +++++++++++++++++++++++++++---
 src/tactic/sls/sls_tracker.h   | 315 ++++++++++++++++++++++++++++++---
 3 files changed, 600 insertions(+), 102 deletions(-)

diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index cdb08038f..696d7664a 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -78,7 +78,11 @@ public:
             case OP_AND: {
                 m_mpz_manager.set(result, m_one);
                 for (unsigned i = 0; i < n_args; i++)
+#if _DIRTY_UP_
+                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i]))  {
+#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result))  {
+#endif
                         m_mpz_manager.set(result, m_zero);
                         break;
                     }
@@ -86,7 +90,11 @@ public:
             }
             case OP_OR: {
                 for (unsigned i = 0; i < n_args; i++)
+#if _DIRTY_UP_
+                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i]))  {
+#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) {
+#endif
                         m_mpz_manager.set(result, m_one);
                         break;
                     }
@@ -94,9 +102,16 @@ public:
             }
             case OP_NOT: {
                 SASSERT(n_args == 1);
+#if _DIRTY_UP_
+                if (m_tracker.is_top_expr(args[0]))
+                    m_mpz_manager.set(result, m_zero);
+                else
+                    m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero);
+#else
                 const mpz & child = m_tracker.get_value(args[0]);
                 SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child));                
-                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);                
+                m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);
+#endif
                 break;
             }
             case OP_EQ: {
@@ -542,7 +557,8 @@ public:
                 m_tracker.set_value(cur, new_value);
 
 #if _REAL_RS_ || _REAL_PBFS_
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                 {
                     if (m_mpz_manager.eq(new_value,m_one))
                         m_tracker.make_assertion(cur);
@@ -554,7 +570,8 @@ public:
 #if _EARLY_PRUNE_
                 new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
@@ -562,13 +579,14 @@ public:
 #else
 #if _CACHE_TOP_SCORE_
                 new_score = m_tracker.score(cur);
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif            
+#endif			
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -611,7 +629,8 @@ public:
 #if _EARLY_PRUNE_
                 new_score = m_tracker.score(cur);
 #if _CACHE_TOP_SCORE_
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
@@ -619,13 +638,14 @@ public:
 #else
 #if _CACHE_TOP_SCORE_
                 new_score = m_tracker.score(cur);
-                if (!m_tracker.has_uplinks(cur))
+                //if (!m_tracker.has_uplinks(cur))
+                if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif            
+#endif			
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -695,7 +715,7 @@ public:
 
         double prune_score, new_score;
         unsigned pot_benefits = 0;
-         SASSERT(cur_depth < m_traversal_stack_bool.size());
+        SASSERT(cur_depth < m_traversal_stack_bool.size());
  
         ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
 
@@ -704,7 +724,8 @@ public:
 
             new_score = m_tracker.score(cur); 
 #if _CACHE_TOP_SCORE_
-            if (!m_tracker.has_uplinks(cur))
+            //if (!m_tracker.has_uplinks(cur))
+            if (m_tracker.is_top_expr(cur))
                 m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
 #endif
             prune_score = m_tracker.get_score_prune(cur);
@@ -745,7 +766,8 @@ public:
 
 #if _CACHE_TOP_SCORE_
                     new_score = m_tracker.score(cur); 
-                    if (!m_tracker.has_uplinks(cur))
+                    //if (!m_tracker.has_uplinks(cur))
+                    if (m_tracker.is_top_expr(cur))
                         m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
 #else
@@ -833,44 +855,7 @@ public:
     }
 #endif
 
-    void randomize_local(expr * e, unsigned int flip) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_constants(e);
-
-        // Randomize _one_ candidate:
-        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
-        func_decl * fd = unsat_constants[r];
-#if _PERC_CHANGE_
-        sort * srt = fd->get_range();
-        mpz temp;
-
-        if (m_manager.is_bool(srt))
-            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-        else
-        {
-            mpz temp2, mask;
-            unsigned bv_sz = m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(temp, m_tracker.get_value(fd));
-
-            for (unsigned bit = 0; bit < bv_sz; bit++)
-                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-                {
-                    m_mpz_manager.set(mask, m_powers(bit));
-                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
-                    m_mpz_manager.set(temp, temp2);
-                }
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(temp2);
-        }
-#else
-        mpz temp = m_tracker.get_random(fd->get_range());
-#endif
-        update(fd, temp);
-        m_mpz_manager.del(temp);
-    } 
-
-     void randomize_local(goal_ref const & g, unsigned int flip) {
-        ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, flip);
-
+    void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _all_ candidates:
 
         //// bool did_something = false;
@@ -927,6 +912,15 @@ public:
                         tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
                         tout << "Locally randomized model: " << std::endl; 
                         m_tracker.show_model(tout); );
+
+    }
+
+    void randomize_local(expr * e) {
+        randomize_local(m_tracker.get_constants(e));
+    } 
+
+     void randomize_local(goal_ref const & g, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(g, flip));
     } 
 };
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 553acc35a..ada0ec359 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -34,6 +34,8 @@ Notes:
 #include"propagate_values_tactic.h"
 #include"sls_tactic.h"
 #include"nnf_tactic.h"
+#include"luby.h"
+#include "ctx_simplify_tactic.h"
 
 // which unsatisfied assertion is selected? only works with _FOCUS_ > 0
 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
@@ -43,9 +45,23 @@ Notes:
 // 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
 #define _FOCUS_ 1
 
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 0
+
 // do we use restarts?
-// 0 = no, otherwise the value defines the maximum number of moves
-#define _RESTARTS_ 0
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 3.0
 
 // timelimit
 #define _TIMELIMIT_ 3600
@@ -66,38 +82,58 @@ Notes:
 // 2 = yes, by squaring it
 // 3 = yes, by setting it to zero
 // 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 0
+#define _WEIGHT_DIST_ 1
 
 // the factor used for _WEIGHT_DIST_ = 1
 #define _WEIGHT_DIST_FACTOR_ 0.25
 
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
 // do we use intensification steps in local minima? if so, how many?
 #define _INTENSIFICATION_ 0
 #define _INTENSIFICATION_TRIES_ 0
 
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 0
+#define _UCT_ 1
 
 // how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 0.01
+#define _UCT_CONSTANT_ 10.0
 
 // is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
 #define _PROBABILISTIC_UCT_ 0
 
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 1
+
 // shall we use addition/subtraction?
 #define _USE_ADDSUB_ 1
 
 // shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 1
+#define _USE_MUL2DIV2_ 0
 
 // shall we try multiplication by 3?
-#define _USE_MUL3_ 1
+#define _USE_MUL3_ 0
 
 // shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 1
+#define _USE_UNARY_MINUS_ 0
 
 // is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 1
+#define _UNIFORM_RANDOM_ 0
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
@@ -124,13 +160,21 @@ Notes:
 #define _CACHE_TOP_SCORE_ 1
 
 
-#if ((_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1) || _BFS_ && (_UCT_ ||_UNIFORM_RANDOM_ ||_REAL_RS_ ||_REAL_PBFS_)
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
     InvalidConfiguration;
 #endif
 #if (_PROBABILISTIC_UCT_ && !_UCT_)
     InvalidConfiguration;
 #endif
-
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+    InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+    InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+    InvalidConfiguration;
+#endif
 
 #include"sls_params.hpp"
 #include"sls_evaluator.h"
@@ -180,6 +224,7 @@ class sls_tactic : public tactic {
         sls_tracker     m_tracker;
         sls_evaluator   m_evaluator;
 
+        unsigned		m_restart_limit;
         unsigned        m_max_restarts;
         unsigned        m_plateau_limit;
 
@@ -208,6 +253,41 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(m_two);
         }        
 
+        double get_restart_armin(unsigned cnt_restarts)
+        {
+            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+            //printf("armin: %f\n", pow(1.1, inner_id + 1));
+            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
+        }
+
+        inline unsigned check_restart(unsigned curr_value)
+        {
+            if (curr_value > m_restart_limit)
+            {
+#if _RESTART_SCHEME_ == 4
+                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+#elif _RESTART_SCHEME_ == 3
+                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 2
+                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 1
+                if (m_stats.m_restarts & 1)
+                    m_restart_limit += _RESTART_LIMIT_;
+                else
+                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+#else
+                    m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
+                return 0;
+            }
+            return 1;
+        }
+
         ast_manager & m() const { return m_manager; }
 
         void set_cancel(bool f) { m_cancel = f; }
@@ -435,12 +515,10 @@ class sls_tactic : public tactic {
                 NOT_IMPLEMENTED_YET();
         }
 
-        void mk_random_move(goal_ref const & g) {
+        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
+        {
             unsigned rnd_mv = 0;
-            if (m_stats.m_moves > 10000)
-                rnd_mv = 0;
 
-            ptr_vector<func_decl> & unsat_constants = m_tracker.get_unsat_constants(g, m_stats.m_moves);                
             unsigned ucc = unsat_constants.size(); 
             unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
             func_decl * fd = unsat_constants[rc];
@@ -503,6 +581,10 @@ class sls_tactic : public tactic {
             m_mpz_manager.del(new_value);
         }
 
+        void mk_random_move(goal_ref const & g) {
+            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
+        }
+
         // will use VNS to ignore some possible moves and increase the flips per second
         double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
                               unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
@@ -857,7 +939,7 @@ class sls_tactic : public tactic {
                 m_stats.m_flips++;
 
                 global_score = incremental_score(g, fd, new_value);
-                 local_score = m_tracker.get_score(q);
+                local_score = m_tracker.get_score(q);
 
                 SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
 
@@ -875,6 +957,130 @@ class sls_tactic : public tactic {
             unsigned new_const = (unsigned)-1, new_bit = 0;        
             mpz new_value;
             move_type move;
+            unsigned plateau_cnt = 0;
+
+            score = rescore(g);
+            unsigned sz = g->size();
+#if _PERC_STICKY_
+            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+
+#if _RESTARTS_ == 1
+            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 2
+            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 3
+            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
+                checkpoint();
+                m_stats.m_moves++;
+
+#if _REAL_RS_ || _REAL_PBFS_
+                //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
+
+#if _FOCUS_
+#if _PERC_STICKY_
+                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#else
+                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+                if (!e)
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+                if (!to_evaluate.size())
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+#endif
+
+#if _TYPE_RSTEP_
+                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                {
+#if _TYPE_RSTEP_ == 1
+                    m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
+                    mk_random_move(to_evaluate);
+#endif
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                }
+                continue;
+#endif
+
+#if _WEIGHT_DIST_ == 4
+                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
+                old_score = score;
+                new_const = (unsigned)-1;
+
+#if _VNS_
+                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+
+                if (new_const == static_cast<unsigned>(-1)) {
+                    score = old_score;
+                    plateau_cnt++;
+#if _INTENSIFICATION_
+                    handle_plateau(g, score);
+                    //handle_plateau(g);
+                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                        mk_random_move(to_evaluate);
+                    else
+#endif
+#if _REPICK_
+                    m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
+                    m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
+
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                } else {
+                    func_decl * fd = to_evaluate[new_const];              
+#if _REAL_RS_ || _REAL_PBFS_
+                    score = serious_score(g, fd, new_value);
+#else
+                    score = incremental_score(g, fd, new_value);    
+#endif
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        // main search loop
+        lbool search_old(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
             
             score = rescore(g);
             TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
@@ -887,12 +1093,12 @@ class sls_tactic : public tactic {
 
             // Andreas: Why do we only allow so few plateaus?
 #if _RESTARTS_
-            while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
 #else
             while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
 #endif
                 do {
-                    if (m_stats.m_moves == 5590)
                     checkpoint();
 
 #if _WEIGHT_DIST_ == 4
@@ -1072,7 +1278,11 @@ class sls_tactic : public tactic {
 
             verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
             verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
             verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
             verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
             verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
             verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
@@ -1081,9 +1291,14 @@ class sls_tactic : public tactic {
             verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
             verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
             verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
             verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
             verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
             verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
             verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
             verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
             verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
@@ -1099,21 +1314,30 @@ class sls_tactic : public tactic {
             verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
             
 #if _WEIGHT_DIST_ == 4
-                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
 #endif
             m_tracker.initialize(g);
             lbool res = l_undef;
         
+            m_restart_limit = _RESTART_LIMIT_;
+
             do {
                 checkpoint();
-                // Andreas: I think restarts are too impotant to ignore 99% of them are happening...
-                //if ((m_stats.m_restarts % 100) == 0)                        
-                    report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                
+
+                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
                 res = search(g);
 
                 if (res == l_undef)
-                    m_tracker.randomize();
+                {
+#if _RESTART_INIT_
+                    m_tracker.randomize(g);
+#else
+                    m_tracker.reset(g);
+#endif
+                }
             }
             while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
         
@@ -1121,6 +1345,13 @@ class sls_tactic : public tactic {
 
             if (res == l_true) {    
                 report_tactic_progress("Number of flips:", m_stats.m_moves);
+                for (unsigned i = 0; i < g->size(); i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                    {
+                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                        NOT_IMPLEMENTED_YET(); 
+                    }
+
                 if (m_produce_models) {
                     model_ref mdl = m_tracker.get_model();
                     mc = model2model_converter(mdl.get());
@@ -1183,12 +1414,17 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = alloc(imp, m, m_params, m_stats);
+        imp * d = m_imp;
         #pragma omp critical (tactic_cancel)
         {
-            std::swap(d, m_imp);
+            d = m_imp;
         }
         dealloc(d);
+        d = alloc(imp, m, m_params, m_stats);
+        #pragma omp critical (tactic_cancel) 
+        {
+            m_imp = d;
+        }
     }
     
     virtual void collect_statistics(statistics & st) const {
@@ -1246,6 +1482,9 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
     // conservative gaussian elimination. 
     gaussian_p.set_uint("gaussian_max_occs", 2); 
 
+    params_ref ctx_p;
+    ctx_p.set_uint("max_depth", 32);
+    ctx_p.set_uint("max_steps", 5000000);
     return and_then(and_then(mk_simplify_tactic(m),                             
                              mk_propagate_values_tactic(m),
                              using_params(mk_solve_eqs_tactic(m), gaussian_p),
@@ -1254,6 +1493,10 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
+                        // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
+                        //mk_ctx_simplify_tactic(m, ctx_p),
+                        // Andreas: This one at least eliminates top level duplicates ...
+                        mk_simplify_tactic(m),
                         // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 006bbb888..0aca1f59c 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -65,6 +65,7 @@ private:
     typedef obj_map<expr, value_score> scores_type;    
     typedef obj_map<expr, ptr_vector<expr> > uplinks_type;    
     typedef obj_map<expr, ptr_vector<func_decl> > occ_type;
+    obj_hashtable<expr>	  m_top_expr;
     scores_type           m_scores;
     uplinks_type          m_uplinks;
     entry_point_type      m_entry_points;
@@ -75,15 +76,15 @@ private:
     unsigned              m_touched;
 #endif
 #if _REAL_RS_ || _REAL_PBFS_
-    ptr_vector<expr>      m_unsat_expr;
-    obj_map<expr, unsigned>    m_where_false;
-    expr**                    m_list_false;
+    ptr_vector<expr>	  m_unsat_expr;
+    obj_map<expr, unsigned>	m_where_false;
+    expr**					m_list_false;
 #endif
 #if _CACHE_TOP_SCORE_
-    double                  m_top_sum;
+    double				  m_top_sum;
 #endif
-#if _WEIGHT_DIST_ == 4
-    double                  m_weight_dist_factor;
+#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
+    double				  m_weight_dist_factor;
 #endif
 
 public:    
@@ -104,7 +105,7 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
-#if _WEIGHT_DIST_ == 4
+#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     inline void set_weight_dist_factor(double val) {
         m_weight_dist_factor = val;
     }
@@ -182,12 +183,12 @@ public:
     inline unsigned has_pos_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_pos_occ;
-     }
+    }
 
     inline unsigned has_neg_occ(expr * n) {
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
-     }
+    }
 #endif
 
     inline unsigned get_distance(expr * n) {
@@ -213,11 +214,62 @@ public:
         return m_uplinks.contains(n);
     }
 
+    inline bool is_top_expr(expr * n) {
+        return m_top_expr.contains(n);
+    }
+
     inline ptr_vector<expr> & get_uplinks(expr * n) {
         SASSERT(m_uplinks.contains(n));
         return m_uplinks.find(n);
     }
 
+#if _REAL_RS_ || _REAL_PBFS_
+    void debug_real(goal_ref const & g, unsigned flip)
+    {
+        unsigned count = 0;
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            expr * e = g->form(i);
+            if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e))
+            {
+                printf("iteration %d: ", flip);
+                printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size());
+                exit(4);
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e))
+            {
+                printf("iteration %d: ", flip);
+                printf("form %d is unsat but not in unsat list\n", i);
+                exit(4);
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e))
+            {
+                unsigned pos = m_where_false.find(e);
+                expr * q = m_list_false[pos];
+                if (q != e)
+                {
+                    printf("iteration %d: ", flip);
+                    printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos);
+                    exit(4);
+                }
+            }
+
+            if (m_mpz_manager.eq(get_value(e),m_zero))
+                count++;
+        }
+
+        // should be true now that duplicate assertions are removed
+        if (count != m_where_false.size())
+        {
+                printf("iteration %d: ", flip);
+                printf("%d are unsat but list is of size %d\n", count, m_where_false.size());
+                exit(4);
+        }
+    }
+#endif
+
     void initialize(app * n) {
         // Build score table
         if (!m_scores.contains(n)) {
@@ -327,7 +379,7 @@ public:
             }
         }
         for_each_expr(proc, visited, e);
-     }
+    }
 
     void initialize_recursive(expr * e) {
         if (m_manager.is_and(e) || m_manager.is_or(e)) {
@@ -344,7 +396,7 @@ public:
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
-     }
+    }
 
     void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
@@ -352,6 +404,10 @@ public:
         unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
             expr * e = g->form(i);
+            if (!m_top_expr.contains(e))
+                m_top_expr.insert(e);
+            else
+                printf("this is already in ...\n");
             // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2
             initialize_recursive(proc, visited, e);
@@ -380,18 +436,20 @@ public:
 
 #if _REAL_RS_ || _REAL_PBFS_
         m_list_false = new expr*[sz];
-        for (unsigned i = 0; i < sz; i++)
-              if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-                break_assertion(g->form(i));
+        //for (unsigned i = 0; i < sz; i++)
+        //{
+        //	if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
+        //		break_assertion(g->form(i));
+        //}
 #endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-              setup_occs(g->form(i));
+            setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-        m_touched = 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
 #endif
     }
 
@@ -407,8 +465,12 @@ public:
                 expr * q = m_list_false[m_where_false.size()];
                 m_list_false[pos] = q;
                 m_where_false.find(q) = pos;
+                //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos);
             }
-//            printf("Going in %d\n", m_where_false.size());
+            //else
+                //printf("Erasing %d from %d to %d\n", e, pos);
+//			m_list_false[m_where_false.size()] = 0;
+//			printf("Going in %d\n", m_where_false.size());
         }
         //if (m_unsat_expr.contains(e))
             //m_unsat_expr.erase(e);
@@ -416,12 +478,14 @@ public:
 
     void break_assertion(expr * e)
     {
+        //printf("I'm broken... that's still fine.\n");
         if (!m_where_false.contains(e))
         {
+            //printf("This however is not so cool...\n");
             unsigned pos = m_where_false.size();
             m_list_false[pos] = e;
             m_where_false.insert(e, pos);
-    //        printf("Going in %d\n", m_where_false.size());
+    //		printf("Going in %d\n", m_where_false.size());
         }
         //if (!m_unsat_expr.contains(e))
             //m_unsat_expr.push_back(e);
@@ -522,7 +586,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize() {
+    void randomize(goal_ref const & g) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -534,6 +598,28 @@ public:
         }
 
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
+
+#if _UCT_RESET_
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
+#endif
+    }              
+
+    void reset(goal_ref const & g) {
+        TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
+
+        for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
+            mpz temp = m_zero;
+            set_value(it->m_value, temp);
+            m_mpz_manager.del(temp);
+        }
+
+#if _UCT_RESET_
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
+#endif
     }              
 
 #if _EARLY_PRUNE_
@@ -591,12 +677,20 @@ public:
 #if _SCORE_AND_AVG_
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
+#if _DIRTY_UP_
+                sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 sum += get_score(args[i]);
+#endif
             res = sum / (double) a->get_num_args();
 #else
             double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 if (cur < min) min = cur;
             }
             res = min;
@@ -610,14 +704,22 @@ public:
 #if _SCORE_OR_MUL_
             double inv = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 inv *= (1.0 - get_score(args[i]));
             }
             res = 1.0 - inv;
 #else
             double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
+#if _DIRTY_UP_
+                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
+#else
                 double cur = get_score(args[i]);
+#endif
                 if (cur > max) max = cur;
             }
             res = max;
@@ -772,7 +874,11 @@ public:
             expr * child = a->get_arg(0);
             if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
                 NOT_IMPLEMENTED_YET();
+#if _DIRTY_UP_
+            res = is_top_expr(child) ? 0.0 : score_bool(child, true);
+#else
             res = score_bool(child, true);
+#endif
         }
         else if (m_manager.is_distinct(n)) {
             app * a = to_app(n);
@@ -803,7 +909,11 @@ public:
         if (afid == m_bv_util.get_family_id())
 #endif
 #if _WEIGHT_DIST_ == 1
+#if _WEIGHT_TOGGLE_
+        if (res < 1.0) res *= m_weight_dist_factor;
+#else
         if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
+#endif
 #elif _WEIGHT_DIST_ == 2
         res *= res;
 #elif _WEIGHT_DIST_ == 3
@@ -900,6 +1010,10 @@ public:
     }
 
     ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+        if (sz == 1)
+            return get_constants();
+        m_temp_constants.reset();
+
         for (unsigned i = 0; i < sz; i++) {
             expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
@@ -945,7 +1059,7 @@ public:
     }
 
     ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
-            if (!e)
+            if (!e || m_temp_constants.size())
                 return m_temp_constants;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
             unsigned sz = this_decls.size();
@@ -1033,32 +1147,43 @@ public:
 #if _PROBABILISTIC_UCT_
             double sum_score = 0.0;
             unsigned start_index = get_random_uint(16) % sz;
+            
             for (unsigned i = start_index; i < sz; i++)
             {
                 expr * e = g->form(i);
                 vscore = m_scores.find(e);
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#if _PROBABILISTIC_UCT_ == 2
+                double q = vscore.score * vscore.score; 
+#else
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
                 if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
                     sum_score += q;
                     if (rand() <= (q * RAND_MAX / sum_score) + 1)
                         pos = i;
-                }    
+                }	
             }
             for (unsigned i = 0; i < start_index; i++)
             {
                 expr * e = g->form(i);
                 vscore = m_scores.find(e);
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#if _PROBABILISTIC_UCT_ == 2
+                double q = vscore.score * vscore.score; 
+#else
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
                 if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
                     sum_score += q;
                     if (rand() <= (q * RAND_MAX / sum_score) + 1)
                         pos = i;
-                }    
+                }	
             }
 #else
             double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
                 expr * e = g->form(i);
+//            for (unsigned i = 0; i < m_where_false.size(); i++) {
+//                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
@@ -1078,6 +1203,7 @@ public:
             m_scores.find(g->form(pos)).touched = flip; 
 #endif
             expr * e = g->form(pos);
+//            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
             unsigned int pos = -1;
@@ -1109,7 +1235,7 @@ public:
 #elif _UNIFORM_RANDOM_
             unsigned cnt_unsat = 0, pos = -1;
             for (unsigned i = 0; i < sz; i++)
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;    
+                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
             if (pos == static_cast<unsigned>(-1))
                 return m_temp_constants;
             expr * e = g->form(pos);
@@ -1120,8 +1246,7 @@ public:
             sz = m_where_false.size();
             if (sz == 0)
                 return m_temp_constants;
-            else
-                expr * e = m_list_false[get_random_uint(16) % sz];
+            expr * e = m_list_false[get_random_uint(16) % sz];
 #elif _REAL_PBFS_
             //unsigned pos = m_false_list[flip % m_cnt_false];
             //expr * e = get_unsat_assertion(g, sz, pos);
@@ -1154,6 +1279,142 @@ public:
 #endif
         }
     }
+    
+
+    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
+
+        if (sz == 1)
+            return g->form(0);
+
+        m_temp_constants.reset();
+#if _FOCUS_ == 1
+#if _UCT_
+        unsigned pos = -1;
+        value_score vscore;
+#if _PROBABILISTIC_UCT_
+        double sum_score = 0.0;
+        unsigned start_index = get_random_uint(16) % sz;
+            
+        for (unsigned i = start_index; i < sz; i++)
+        {
+            expr * e = g->form(i);
+            vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+            double q = vscore.score * vscore.score + _UCT_EPS_; 
+#else
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                sum_score += q;
+                if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                    pos = i;
+            }	
+        }
+        for (unsigned i = 0; i < start_index; i++)
+        {
+            expr * e = g->form(i);
+            vscore = m_scores.find(e);
+#if _PROBABILISTIC_UCT_ == 2
+            double q = vscore.score * vscore.score + _UCT_EPS_; 
+#else
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
+#endif
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
+                sum_score += q;
+                if (rand() <= (q * RAND_MAX / sum_score) + 1)
+                    pos = i;
+            }	
+        }
+#else
+        double max = -1.0;
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+//            for (unsigned i = 0; i < m_where_false.size(); i++) {
+//                expr * e = m_list_false[i];
+                vscore = m_scores.find(e);
+#if _UCT_ == 1
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+#elif _UCT_ == 2
+            double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#endif
+            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+            }
+#endif
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+
+#if _UCT_ == 1
+        m_scores.find(g->form(pos)).touched++;
+        m_touched++;
+#elif _UCT_ == 2
+        m_scores.find(g->form(pos)).touched = flip; 
+#endif
+//        return m_list_false[pos];
+        return g->form(pos);
+
+#elif _BFS_ == 3
+        unsigned int pos = -1;
+        double max = -1.0;
+        for (unsigned i = 0; i < sz; i++) {
+            expr * e = g->form(i);
+               double q = get_score(e);
+            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _BFS_ == 2
+        unsigned int pos = -1;
+        double min = 2.0;
+        for (unsigned i = 0; i < sz; i++) {
+            expr * e = g->form(i);
+               double q = get_score(e);
+            if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
+        }
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _BFS_ == 1
+        unsigned int pos = flip % sz;
+        return get_unsat_assertion(g, sz, pos);
+#elif _UNIFORM_RANDOM_
+        unsigned cnt_unsat = 0, pos = -1;
+        for (unsigned i = 0; i < sz; i++)
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+#elif _REAL_RS_
+        //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
+        //expr * e = get_unsat_assertion(g, sz, pos);
+        //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
+        sz = m_where_false.size();
+        if (sz == 0)
+            return 0;
+        return m_list_false[get_random_uint(16) % sz];
+#elif _REAL_PBFS_
+        //unsigned pos = m_false_list[flip % m_cnt_false];
+        //expr * e = get_unsat_assertion(g, sz, pos);
+        //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
+        sz = m_where_false.size();
+        if (sz == 0)
+            return0;
+        else
+            return m_list_false[flip % sz];
+#else
+        unsigned int pos = get_random_uint(16) % sz;
+        return get_unsat_assertion(g, sz, pos);
+#endif
+        return g->form(pos);
+#elif _FOCUS_ == 2
+#if _BFS_
+        unsigned int pos = flip % sz;
+#else
+        unsigned int pos = get_random_uint(16) % sz;
+#endif
+        return get_unsat_constants_crsat(g, sz, pos);
+#endif
+    }
 };
 
 #endif
\ No newline at end of file

From 7451e5cae0ccdf110065453d8918f7f2e7726d4a Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 17:04:38 +0000
Subject: [PATCH 071/108] SLS refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h |  158 +++
 src/tactic/sls/sls_engine.cpp             | 1027 +++++++++++----
 src/tactic/sls/sls_engine.h               |   88 +-
 src/tactic/sls/sls_evaluator.h            |    3 +
 src/tactic/sls/sls_tactic.cpp             | 1397 +--------------------
 src/tactic/sls/sls_tracker.h              |   10 +-
 6 files changed, 1036 insertions(+), 1647 deletions(-)
 create mode 100644 src/tactic/sls/sls_compilation_settings.h

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
new file mode 100644
index 000000000..aea4787b0
--- /dev/null
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -0,0 +1,158 @@
+/*++
+Copyright (c) 2014 Microsoft Corporation
+
+Module Name:
+
+    sls_compilation_constants.h
+
+Abstract:
+
+    Stochastic Local Search (SLS) compilation constants
+
+Author:
+
+    Christoph (cwinter) 2014-03-19
+
+Notes:
+
+    This file should go away completely once we have evaluated all options.
+
+--*/
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
+#define _FOCUS_ 1
+
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 0
+
+// do we use restarts?
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 3.0
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
+#define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
+#define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
+#define _VNS_ 0
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 1
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.25
+
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 1
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 10.0
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
+#define _PROBABILISTIC_UCT_ 0
+
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 1
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 0
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 0
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 0
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 0
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
+InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+InvalidConfiguration;
+#endif
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+InvalidConfiguration;
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index c0c319ab4..92471aad8 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -16,7 +16,6 @@ Author:
 Notes:
 
 --*/
-#include<float.h>
 #include<iomanip>
 
 #include"map.h"
@@ -28,6 +27,7 @@ Notes:
 #include"cooperate.h"
 #include"luby.h"
 
+#include"sls_compilation_settings.h"
 #include"sls_params.hpp"
 #include"sls_engine.h"
 
@@ -44,7 +44,6 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) :
     m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers)
 {
     updt_params(p);
-    m_tracker.updt_params(p);
 }
 
 sls_engine::~sls_engine() {
@@ -53,32 +52,20 @@ sls_engine::~sls_engine() {
     m_mpz_manager.del(m_two);
 }
 
+double sls_engine::get_restart_armin(unsigned cnt_restarts)
+{
+    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+    //printf("armin: %f\n", pow(1.1, inner_id + 1));
+    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
+}    
+
 void sls_engine::updt_params(params_ref const & _p) {
     sls_params p(_p);
     m_produce_models = _p.get_bool("model", false);
-    m_max_restarts = p.max_restarts();
+    m_max_restarts = p.restarts();
     m_tracker.set_random_seed(p.random_seed());
-    m_walksat = p.walksat();
-    m_walksat_repick = p.walksat_repick();
-    m_paws_sp = p.paws_sp();
-    m_paws = m_paws_sp < 1024;
-    m_wp = p.wp();
-    m_vns_mc = p.vns_mc();
-    m_vns_repick = p.vns_repick();
-
-    m_restart_base = p.restart_base();
-    m_restart_next = m_restart_base;
-    m_restart_init = p.restart_init();
-
-    m_early_prune = p.early_prune();
-    m_random_offset = p.random_offset();
-    m_rescore = p.rescore();
-
-    // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
-    if (m_walksat_repick && !m_walksat)
-        NOT_IMPLEMENTED_YET();
-    if (m_vns_repick && !m_walksat)
-        NOT_IMPLEMENTED_YET();
+    m_plateau_limit = p.plateau_limit();
 }
 
 void sls_engine::checkpoint() {
@@ -87,15 +74,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(model & mdl) {
+bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     bool res = true;
 
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(m_assertions[i], o, true))
+        if (!mdl.eval(g->form(i), o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -106,69 +93,96 @@ bool sls_engine::full_eval(model & mdl) {
     return res;
 }
 
-double sls_engine::top_score() {
+double sls_engine::top_score(goal_ref const & g) {
+#if 0
+    double min = m_tracker.get_score(g->form(0));
+    unsigned sz = g->size();
+    for (unsigned i = 1; i < sz; i++) {
+        double q = m_tracker.get_score(g->form(i));
+        if (q < min) min = q;
+    }
+    TRACE("sls_top", tout << "Score distribution:";
+    for (unsigned i = 0; i < sz; i++)
+        tout << " " << m_tracker.get_score(g->form(i));
+    tout << " MIN: " << min << std::endl;);
+    return min;
+#else
     double top_sum = 0.0;
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = m_assertions[i];
+        expr * e = g->form(i);
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(m_assertions[i]);
+        tout << " " << m_tracker.get_score(g->form(i));
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
+#if _CACHE_TOP_SCORE_
     m_tracker.set_top_sum(top_sum);
+#endif
 
-    return top_sum;
+    return top_sum / (double)sz;
+#endif
 }
 
-double sls_engine::rescore() {
+double sls_engine::rescore(goal_ref const & g) {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score();
+    return top_score(g);
 }
 
-double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
-    return m_tracker.get_top_sum();
+#if _CACHE_TOP_SCORE_
+    return (m_tracker.get_top_sum() / g->size());
+#else
+    return top_score(g);
+#endif
 }
 
-double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
-    return m_tracker.get_top_sum();
+#if _CACHE_TOP_SCORE_
+    return (m_tracker.get_top_sum() / g->size());
+#else
+    return top_score(g);
+#endif
 }
 
-double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+#if _EARLY_PRUNE_
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
-        return m_tracker.get_top_sum();
+#if _CACHE_TOP_SCORE_
+        return (m_tracker.get_top_sum() / g->size());
+#else
+        return top_score(g);
+#endif
     else
-        return -DBL_MAX;
+        return 0.0;
+#else
+    NOT_IMPLEMENTED_YET();
+#endif
 }
 
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(
-    func_decl * fd, 
-    const unsigned & fd_inx, 
-    const mpz & temp,
-    double & best_score, 
-    unsigned & best_const, 
-    mpz & best_value) {
+bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
     m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 #endif
 
-    double r;
-    if (m_early_prune)
-        r = incremental_score_prune(fd, temp);
-    else
-        r = incremental_score(fd, temp);
+#if _EARLY_PRUNE_
+    double r = incremental_score_prune(g, fd, temp);
+#else
+    double r = incremental_score(g, fd, temp);
+#endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
             " --> " << r << std::endl;);
@@ -176,10 +190,7 @@ bool sls_engine::what_if(
     m_mpz_manager.del(old_value);
 #endif
 
-    // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection.
-    // r += 0.0001 * m_tracker.get_random_uint(8);
-
-    // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
+    //            if (r >= best_score) {
     if (r > best_score) {
         best_score = r;
         best_const = fd_inx;
@@ -190,6 +201,21 @@ bool sls_engine::what_if(
     return false;
 }
 
+// same as what_if, but only applied to the score of a specific atom, not the total score
+bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                    double & best_score, unsigned & best_const, mpz & best_value) {
+    m_evaluator.update(fd, temp);
+    double r = m_tracker.get_score(e);
+    if (r >= best_score) {
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
 void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
     mpz temp, mask, mask2;
     m_mpz_manager.add(old_value, add_value, temp);
@@ -202,6 +228,22 @@ void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value,
 
 }
 
+// Andreas: do we really need all those temporary mpzs?
+void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+    mpz temp, mask, mask2;
+    m_mpz_manager.mul(old_value, m_two, temp);
+    m_mpz_manager.set(mask, m_powers(bv_sz));
+    m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+    m_mpz_manager.bitwise_and(temp, mask2, result);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(mask);
+    m_mpz_manager.del(mask2);
+}
+
+void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+    m_mpz_manager.div(old_value, m_two, result);
+}
+
 void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
     unsigned shift;
     m_mpz_manager.add(old_value, m_one, incremented);
@@ -251,18 +293,16 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
     else
     {
+#if _USE_ADDSUB_
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-
-        // Andreas: The other option would be to scale the probability for flips according to the bit-width.
-        /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt);
-        rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3);
-        if (rnd_mv > 3) rnd_mv = 0; */
-
         move_type mt = (move_type)rnd_mv;
 
-        // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true?
+        // inversion doesn't make sense, let's do a flip instead.
         if (mt == MV_INV) mt = MV_FLIP;
+#else
+        mt = MV_FLIP;
+#endif
         unsigned bit = 0;
 
         switch (mt)
@@ -300,30 +340,192 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout););
     }
 
-    m_evaluator.serious_update(fd, new_value);
+    m_evaluator.update(fd, new_value);
     m_mpz_manager.del(new_value);
 }
 
-// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(
-    ptr_vector<func_decl> & to_evaluate, 
-    double score,
-    unsigned & best_const, 
-    mpz & best_value, 
-    unsigned & new_bit, 
-    move_type & move) 
-{
+void sls_engine::mk_random_move(goal_ref const & g) {
+    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
+}
+
+// will use VNS to ignore some possible moves and increase the flips per second
+double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
     mpz old_value, temp;
+    unsigned bv_sz, max_bv_sz = 0;
+    double new_score = score;
+
+    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+            // try to flip lsb
+            mk_flip(srt, old_value, 0, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = 0;
+                move = MV_FLIP;
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        SASSERT(check == score);
+    }
+
+    // we can either check the condition once in the beginning or check it repeatedly after every bit
+#if _VNS_ == 1
+    for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+    if (new_score <= score)
+        for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
+// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+    mpz temp2;
+#endif
     unsigned bv_sz;
     double new_score = score;
 
-    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
-    unsigned sz = to_evaluate.size();
-    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
-    for (unsigned j = 0; j < sz; j++) {
-        unsigned i = j + offset;
-        if (i >= sz) i -= sz;
-    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
+    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        // first try to flip every bit
+#if _SKIP_BITS_
+        for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
+#else
+        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+            // What would happen if we flipped bit #i ?                
+            mk_flip(srt, old_value, j, temp);
+
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = j;
+                move = MV_FLIP;
+            }
+        }
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+#if _USE_ADDSUB_
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+#endif
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+            mk_inc(bv_sz, temp, temp2);
+            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+            // try multiplication by 2
+            mk_mul2(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_MUL2;
+
+#if _USE_MUL3_
+            // try multiplication by 3
+            mk_add(bv_sz, old_value, temp, temp2);
+            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                move = MV_MUL3;
+#endif
+
+            // try division by 2
+            mk_div2(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_DIV2;
+#endif
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        // Andreas: does not hold anymore now that we use top level score caching
+        //SASSERT(check == score);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+#if _USE_MUL3_
+    m_mpz_manager.del(temp2);
+#endif
+    return new_score;
+}
+
+// same as find_best_move but only considers the score of the current expression instead of the overall score
+double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+    unsigned bv_sz;
+    double new_score = m_tracker.get_score(e);
+    // Andreas: tie breaking not implemented yet
+    // double tie_score = top_score(g);
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -334,7 +536,7 @@ double sls_engine::find_best_move(
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
@@ -344,176 +546,489 @@ double sls_engine::find_best_move(
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
+
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(fd, i, temp, new_score, best_const, best_value))
+            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
         }
+
         // reset to what it was before
-        incremental_score(fd, old_value);
+        m_evaluator.update(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
     m_mpz_manager.del(temp);
-
     return new_score;
 }
 
-// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double score,
-                        unsigned & best_const, mpz & best_value) {
-    mpz old_value, temp, temp2;
-    unsigned bv_sz;
-    double new_score = score;
+// first try of intensification ... does not seem to be efficient
+bool sls_engine::handle_plateau(goal_ref const & g)
+{
+    unsigned sz = g->size();
+#if _BFS_
+    unsigned pos = m_stats.m_moves % sz;
+#else
+    unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+    if (!e)
+        return 0;
 
-    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
-    unsigned sz = to_evaluate.size();
-    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
-    for (unsigned j = 0; j < sz; j++) {
-        unsigned i = j + offset;
-        if (i >= sz) i -= sz;
-    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
-        func_decl * fd = to_evaluate[i];
-        sort * srt = fd->get_range();
-        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+    expr * q = m_tracker.get_unsat_expression(e);
+    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+    for (unsigned i = 0; i < to_evaluate.size(); i++)
+    {
+        m_tracker.get_value(to_evaluate[i]);
+        m_old_values.push_back(&m_tracker.get_value(to_evaluate[i]));
+    }
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+    for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+    {
+        // Andreas: Could be extended to use (best) score but this is computationally more expensive.
+        find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
 
-        if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) {
-            for (unsigned j = 0; j < bv_sz; j++) {
-                mk_flip(srt, old_value, j, temp);
-                for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++)
-                {
-                    unsigned k = m_tracker.get_random_uint(16) % bv_sz;
-                    while (k == j)
-                        k = m_tracker.get_random_uint(16) % bv_sz;
-                    mk_flip(srt, temp, k, temp2);
-                    what_if(fd, i, temp2, new_score, best_const, best_value);
-                }
-            }
+        if (new_const == static_cast<unsigned>(-1)) {
+            // Andreas: Actually this should never happen.
+            NOT_IMPLEMENTED_YET();
         }
-        // reset to what it was before
-        incremental_score(fd, old_value);
+        else {
+            m_stats.m_moves++;
+            func_decl * fd = to_evaluate[new_const];
+
+            switch (move) {
+            case MV_FLIP: m_stats.m_flips++; break;
+            case MV_INC: m_stats.m_incs++; break;
+            case MV_DEC: m_stats.m_decs++; break;
+            case MV_INV: m_stats.m_invs++; break;
+            case MV_UMIN: m_stats.m_umins++; break;
+            case MV_MUL2: m_stats.m_mul2s++; break;
+            case MV_MUL3: m_stats.m_mul3s++; break;
+            case MV_DIV2: m_stats.m_div2s++; break;
+            }
+
+            m_evaluator.update(fd, new_value);
+        }
+
+        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+            return 1;
+    }
+
+    for (unsigned i = 0; i < to_evaluate.size(); i++)
+        m_tracker.set_value(to_evaluate[i], *m_old_values[i]);
+
+    m_old_values.reset();
+
+    return 0;
+}
+
+// what_if version needed in the context of 2nd intensification try, combining local and global score
+bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                double & best_score, mpz & best_value, unsigned i) {
+
+    double global_score = incremental_score(g, fd, temp);
+    double local_score = m_tracker.get_score(e);
+    double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+    if (new_score >= best_score) {
+        best_score = new_score;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+
+    return false;
+}
+
+// find_best_move version needed in the context of 2nd intensification try
+double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+{
+    mpz old_value, temp;
+    double best_score = 0;
+
+    sort * srt = fd->get_range();
+    unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+    m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+    for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+        mk_flip(srt, old_value, j, temp);
+        what_if(g, e, fd, temp, best_score, best_value, i);
     }
 
     m_mpz_manager.del(old_value);
     m_mpz_manager.del(temp);
-    m_mpz_manager.del(temp2);
 
-    return new_score;
+    return best_score;
+}
+
+// second try to use intensification ... also not very effective
+bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
+{
+    unsigned sz = g->size();
+#if _BFS_
+    unsigned new_const = m_stats.m_moves % sz;
+#else
+    unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+    if (!e)
+        return 0;
+
+    expr * q = m_tracker.get_unsat_expression(e);
+    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+    new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+    func_decl * fd = to_evaluate[new_const];
+
+    mpz new_value;
+    //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+    unsigned new_bit = 0;
+    double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+
+    for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+    {
+        new_score = find_best_move_local(g, q, fd, new_value, i);
+
+        m_stats.m_moves++;
+        m_stats.m_flips++;
+
+        global_score = incremental_score(g, fd, new_value);
+        local_score = m_tracker.get_score(q);
+
+        SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+            return 1;
+    }
+
+    return 0;
 }
 
 // main search loop
-lbool sls_engine::search() {
+lbool sls_engine::search(goal_ref const & g) {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
-    unsigned new_const = (unsigned)-1, new_bit;
+    unsigned new_const = (unsigned)-1, new_bit = 0;
     mpz new_value;
     move_type move;
+    unsigned plateau_cnt = 0;
 
-    score = rescore();
-    unsigned sz = m_assertions.size();
+    score = rescore(g);
+    unsigned sz = g->size();
+#if _PERC_STICKY_
+    expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#endif
 
-    while (check_restart(m_stats.m_moves)) {
+#if _RESTARTS_ == 1
+    while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#elif _RESTARTS_ == 2
+    while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#elif _RESTARTS_ == 3
+    while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#else
+    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
+#endif
         checkpoint();
         m_stats.m_moves++;
 
-        // Andreas: Every base restart interval ...
-        if (m_stats.m_moves % m_restart_base == 0)
-        {
-            // ... potentially smooth the touched counters ...
-            m_tracker.ucb_forget(m_assertions);
-            // ... or normalize the top-level score.
-            if (m_rescore) score = rescore();
-        }
+#if _REAL_RS_ || _REAL_PBFS_
+        //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
 
-        // get candidate variables
-        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
+#if _FOCUS_
+#if _PERC_STICKY_
+        if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+            e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#else
+        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+#endif
+        if (!e)
+        {
+            res = l_true;
+            goto bailout;
+        }
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
         if (!to_evaluate.size())
         {
             res = l_true;
             goto bailout;
         }
+#endif
 
-        // random walk with probability wp / 1024
-        if (m_wp && m_tracker.get_random_uint(10) < m_wp)
+#if _TYPE_RSTEP_
+        if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
         {
+#if _TYPE_RSTEP_ == 1
+            m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
             mk_random_move(to_evaluate);
-            score = m_tracker.get_top_sum();
-            continue;
+#endif
+#if _CACHE_TOP_SCORE_
+            score = m_tracker.get_top_sum() / g->size();
+#else
+            score = top_score(g);
+#endif
         }
+        continue;
+#endif
 
+#if _WEIGHT_DIST_ == 4
+        m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
         old_score = score;
         new_const = (unsigned)-1;
 
-        // find best increasing move
-        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
+#if _VNS_
+        score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
 
-        // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously
-        if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
-            score = find_best_move_mc(to_evaluate, score, new_const, new_value);
-   
-        // repick assertion if no increasing move was found previously
-        if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
-        {
-            expr * q = m_tracker.get_new_unsat_assertion(m_assertions);
-            // only apply if another unsatisfied assertion actually exists
-            if (q)
-            {
-                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q);
-                score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move);
-
-                if (new_const != static_cast<unsigned>(-1)) {
-                    func_decl * fd = to_evaluate2[new_const];
-                    score = serious_score(fd, new_value);
-                    continue;
-                }
-            }
-        }
-
-        // randomize if no increasing move was found
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
-            if (m_walksat_repick)
-                m_evaluator.randomize_local(m_assertions);
+            plateau_cnt++;
+#if _INTENSIFICATION_
+            handle_plateau(g, score);
+            //handle_plateau(g);
+            //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+            //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+            if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                mk_random_move(to_evaluate);
             else
+#endif
+#if _REPICK_
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
                 m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
 
-            score = m_tracker.get_top_sum();
-
-            // update assertion weights if a weigthing is enabled (sp < 1024)
-            if (m_paws)
-            {
-                for (unsigned i = 0; i < sz; i++)
-                {
-                    expr * q = m_assertions[i];
-                    // smooth weights with probability sp / 1024
-                    if (m_tracker.get_random_uint(10) < m_paws_sp)
-                    {
-                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
-                            m_tracker.decrease_weight(q);
-                    }
-                    // increase weights otherwise
-                    else
-                    {
-                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
-                            m_tracker.increase_weight(q);
-                    }
-                }
-            }
+#if _CACHE_TOP_SCORE_
+            score = m_tracker.get_top_sum() / g->size();
+#else
+            score = top_score(g);
+#endif
         }
-        // otherwise, apply most increasing move
         else {
             func_decl * fd = to_evaluate[new_const];
-            score = serious_score(fd, new_value);
+#if _REAL_RS_ || _REAL_PBFS_
+            score = serious_score(g, fd, new_value);
+#else
+            score = incremental_score(g, fd, new_value);
+#endif
+        }
+    }
+
+bailout:
+    m_mpz_manager.del(new_value);
+
+    return res;
+}
+
+// main search loop
+lbool sls_engine::search_old(goal_ref const & g) {
+    lbool res = l_undef;
+    double score = 0.0, old_score = 0.0;
+    unsigned new_const = (unsigned)-1, new_bit = 0;
+    mpz new_value;
+    move_type move;
+
+    score = rescore(g);
+    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+    tout << "Score distribution:";
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    tout << " TOP: " << score << std::endl;);
+
+    unsigned plateau_cnt = 0;
+
+    // Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+    while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+        //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {
+#endif
+        do {
+            checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+
+#if _TYPE_RSTEP_
+            if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+            {
+#if _TYPE_RSTEP_ == 1
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+                mk_random_move(g);
+#endif
+                score = top_score(g);
+
+                if (score >= 1.0) {
+                    bool all_true = true;
+                    for (unsigned i = 0; i < g->size() && all_true; i++)
+                        if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                            all_true = false;
+                    if (all_true) {
+                        res = l_true; // sat
+                        goto bailout;
+                    }
+                    else
+                        TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                }
+            }
+#endif
+            old_score = score;
+            new_const = (unsigned)-1;
+
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+            if (!to_evaluate.size())
+            {
+                res = l_true;
+                goto bailout;
+            }
+            TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                tout << to_evaluate[i]->get_name() << std::endl;);
+
+#if _VNS_
+            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+            if (new_const == static_cast<unsigned>(-1)) {
+                TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
+                for (unsigned i = 0; i < g->size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                });
+
+                TRACE("sls_max", m_tracker.show_model(tout);
+                tout << "Scores: " << std::endl;
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
+                    m_tracker.get_score(g->form(i)) << std::endl;);
+                // Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                score = old_score;
+            }
+            else {
+                // Andreas: Why does randomizing not count as a move? (Now it does.)
+                m_stats.m_moves++;
+                func_decl * fd = to_evaluate[new_const];
+
+                TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
+                switch (move) {
+                case MV_FLIP:
+                    tout << "Flip";
+                    if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
+                    break;
+                case MV_INC:
+                    tout << "+1";
+                    break;
+                case MV_DEC:
+                    tout << "-1";
+                    break;
+                case MV_INV:
+                    tout << "NEG";
+                    break;
+                };
+                tout << ") ; new score = " << std::setprecision(32) << score << std::endl;);
+
+                switch (move) {
+                case MV_FLIP: m_stats.m_flips++; break;
+                case MV_INC: m_stats.m_incs++; break;
+                case MV_DEC: m_stats.m_decs++; break;
+                case MV_INV: m_stats.m_invs++; break;
+                case MV_UMIN: m_stats.m_umins++; break;
+                case MV_MUL2: m_stats.m_mul2s++; break;
+                case MV_MUL3: m_stats.m_mul3s++; break;
+                case MV_DIV2: m_stats.m_div2s++; break;
+                }
+
+#if _REAL_RS_ || _REAL_PBFS_
+                score = serious_score(g, fd, new_value);
+#else
+                score = incremental_score(g, fd, new_value);
+#endif
+
+                TRACE("sls", tout << "Score distribution:";
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                tout << " TOP: " << score << std::endl;);
+            }
+
+            if (score >= 0.99999) {
+                //                    if (score >= 1.0) {
+                // score could theoretically be imprecise.
+                // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                bool all_true = true;
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        all_true = false;
+                if (all_true) {
+                    res = l_true; // sat
+                    goto bailout;
+                }
+                else
+                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+            }
+            /*
+            if (m_stats.m_moves % 100 == 0)
+            {
+            verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+            verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+            }*/
+        } while (score > old_score && res == l_undef);
+
+        // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+        if (score != old_score) {
+            report_tactic_progress("This should not happen I guess.", plateau_cnt);
+            plateau_cnt = 0;
+        }
+        else {
+            m_stats.m_moves++;
+            plateau_cnt++;
+            //report_tactic_progress("Plateau.", plateau_cnt);
+            // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+            //if (plateau_cnt < m_plateau_limit) {
+            TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
+#if _INTENSIFICATION_
+            handle_plateau(g, score);
+            //handle_plateau(g);
+#else
+            m_evaluator.randomize_local(g, m_stats.m_moves);
+#endif
+            //mk_random_move(g);
+            score = top_score(g);
+
+            if (score >= 1.0) {
+                bool all_true = true;
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        all_true = false;
+                if (all_true) {
+                    res = l_true; // sat
+                    goto bailout;
+                }
+                else
+                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+            }
         }
     }
 
@@ -531,10 +1046,71 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
-    for (unsigned i = 0; i < g->size(); i++)
-        assert_expr(g->form(i));    
+    verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+    verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+    verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
+    verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+    verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+    verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+    verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
+    verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+    verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+    verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+    verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+    verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+    verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+    verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+    verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+    verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+    verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
+    verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+    verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+    verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+    verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+    verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+    verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+    verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+    verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+    verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+    verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+    verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+    verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+    verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+    verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+    verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+    verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+    verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+    verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-    lbool res = operator()();
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(g);
+    lbool res = l_undef;
+
+    m_restart_limit = _RESTART_LIMIT_;
+
+    do {
+        checkpoint();
+
+        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+        res = search(g);
+
+        if (res == l_undef)
+        {
+#if _RESTART_INIT_
+            m_tracker.randomize(g);
+#else
+            m_tracker.reset(g);
+#endif
+        }
+    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+
+    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
 
     if (res == l_true) {
         report_tactic_progress("Number of flips:", m_stats.m_moves);
@@ -556,66 +1132,29 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         mc = 0;
 }
 
-lbool sls_engine::operator()() {
-    m_tracker.initialize(m_assertions);
-    lbool res = l_undef;
-
-    do {
-        checkpoint();
-
-        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search();
-
-        if (res == l_undef)
-        {
-            if (m_restart_init)
-                m_tracker.randomize(m_assertions);
-            else
-                m_tracker.reset(m_assertions);
-        }
-    } while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
-
-    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-    
-    return res;
-}
-
-/* Andreas: Needed for Armin's restart scheme if we don't want to use loops.
-double sls_engine::get_restart_armin(unsigned cnt_restarts)
-{
-    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
-}    
-*/
-
 unsigned sls_engine::check_restart(unsigned curr_value)
 {
-    if (curr_value > m_restart_next)
+    if (curr_value > m_restart_limit)
     {
-        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter.
-        I leave the other versions as comments in case you want to try it again somewhen.
-#if _RESTART_SCHEME_ == 5
-        m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
-#elif _RESTART_SCHEME_ == 4
-        m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1);
+#if _RESTART_SCHEME_ == 4
+        m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
-        m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base;
+        m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
 #elif _RESTART_SCHEME_ == 2
-        m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base;
+        m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
 #elif _RESTART_SCHEME_ == 1
         if (m_stats.m_restarts & 1)
-            m_restart_next += m_restart_base;
+            m_restart_limit += _RESTART_LIMIT_;
         else
-            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
+            m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
 #else
-        m_restart_limit += m_restart_base;
-#endif  */
-        if (m_stats.m_restarts & 1)
-            m_restart_next += m_restart_base;
-        else
-            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
+        m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+        printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+        m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
         return 0;
     }
     return 1;
-}
+}
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index b056c438e..878354c6d 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,8 +22,8 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
-#include"goal.h"
 
+#include"sls_compilation_settings.h"
 #include"sls_tracker.h"
 #include"sls_evaluator.h"
 
@@ -35,13 +35,17 @@ public:
         stopwatch       m_stopwatch;
         unsigned        m_full_evals;
         unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
 
         stats() :
             m_restarts(0),
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -67,24 +71,14 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
-    ptr_vector<expr> m_assertions;
 
+    unsigned		m_restart_limit;
     unsigned        m_max_restarts;
-    unsigned        m_walksat;
-    unsigned        m_walksat_repick;
-    unsigned        m_wp;
-    unsigned        m_vns_mc;
-    unsigned        m_vns_repick;
-    unsigned        m_paws;
-    unsigned        m_paws_sp;
-    unsigned        m_restart_base;
-    unsigned        m_restart_next;
-    unsigned        m_restart_init;
-    unsigned        m_early_prune;
-    unsigned        m_random_offset;
-    unsigned        m_rescore;
+    unsigned        m_plateau_limit;
 
-    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
+    ptr_vector<mpz> m_old_values;
+
+    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;
 
 public:    
     sls_engine(ast_manager & m, params_ref const & p);
@@ -98,46 +92,68 @@ public:
 
     void updt_params(params_ref const & _p);
 
-    void assert_expr(expr * e) { m_assertions.push_back(e); }
-
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(model & mdl);
+    bool full_eval(goal_ref const & g, model & mdl);
+    
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
+    void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
+    void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result);
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
 
-    lbool search(void);    
+    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    
+    
+    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
+    
+    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    
+
+    lbool search(goal_ref const & g);    
 
-    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
+    lbool search_old(goal_ref const & g);
+    double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
 
-    double top_score();
-    double rescore();
-    double serious_score(func_decl * fd, const mpz & new_value);
-    double incremental_score(func_decl * fd, const mpz & new_value);
+    bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                       double & best_score, unsigned & best_const, mpz & best_value);
 
-    double incremental_score_prune(func_decl * fd, const mpz & new_value);
-    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    double top_score(goal_ref const & g);
+    double rescore(goal_ref const & g);
+    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
 
-    double find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value);
+#if _EARLY_PRUNE_
+    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
+#endif
+
+    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
 
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
+    void mk_random_move(goal_ref const & g);
 
-    //double get_restart_armin(unsigned cnt_restarts);    
-    unsigned check_restart(unsigned curr_value);
+    bool handle_plateau(goal_ref const & g);
+    bool handle_plateau(goal_ref const & g, double old_score);
+
+    inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 696d7664a..9daf93c32 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -20,6 +20,9 @@ Notes:
 #ifndef _SLS_EVALUATOR_H_
 #define _SLS_EVALUATOR_H_
 
+#include"model_evaluator.h"
+
+#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 #include"sls_tracker.h"
 
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index ada0ec359..0f157d3a6 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,1364 +16,31 @@ Author:
 Notes:
 
 --*/
-#include<iomanip>
-#include"map.h"
 #include"nnf.h"
-#include"cooperate.h"
-#include"ast_smt2_pp.h"
-#include"ast_pp.h"
-#include"var_subst.h"
-#include"model_pp.h"
-#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
-#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"stopwatch.h"
 #include"propagate_values_tactic.h"
-#include"sls_tactic.h"
+#include"ctx_simplify_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"nnf_tactic.h"
-#include"luby.h"
-#include "ctx_simplify_tactic.h"
-
-// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
-// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
-#define _BFS_ 0
-
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
-#define _FOCUS_ 1
-
-// probability of choosing the same assertion again in the next step
-#define _PERC_STICKY_ 0
-
-// do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 0
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
-// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 3.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// should score of discunctions be calculated by multiplication of the inverse score rather than min?
-#define _SCORE_OR_MUL_ 0
-
-// do we use some kind of variable neighbourhood-search?
-// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
-#define _VNS_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no
-// 1 = yes, by multiplying it with some factor
-// 2 = yes, by squaring it
-// 3 = yes, by setting it to zero
-// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.25
-
-// shall we toggle the weight after each restart?
-#define _WEIGHT_TOGGLE_ 0
-
-// do we use intensification steps in local minima? if so, how many?
-#define _INTENSIFICATION_ 0
-#define _INTENSIFICATION_TRIES_ 0
-
-// what is the percentage of random moves in plateaus (instead of full randomization)?
-#define _PERC_PLATEAU_MOVES_ 0
-
-// shall we repick clause when randomizing in a plateau or use the current one?
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 10.0
-
-// is uct clause selection probabilistic similar to variable selection in sparrow?
-// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
-#define _PROBABILISTIC_UCT_ 0
-
-// additive constants for probabilistic uct > 0
-#define _UCT_EPS_ 0.0001
-
-// shall we reset _UCT_ touched values after restart?
-#define _UCT_RESET_ 0
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 1
-
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
-// shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 0
-
-// shall we try multiplication by 3?
-#define _USE_MUL3_ 0
-
-// shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 0
-
-// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 0
-
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
-#define _REAL_RS_ 0
-#define _REAL_PBFS_ 0
-
-// how many bits do we neglect in each iteration?
-#define _SKIP_BITS_ 0
-
-// when randomizing local, what is the probability for changing a single bit?
-// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
-#define _PERC_CHANGE_ 0
-
-// do we use random steps for noise?
-// 0 = no, 1 = randomize local, 2 = make random move
-#define _TYPE_RSTEP_ 0
-
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
-
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-
-#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
-    InvalidConfiguration;
-#endif
-#if (_PROBABILISTIC_UCT_ && !_UCT_)
-    InvalidConfiguration;
-#endif
-#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
-    InvalidConfiguration;
-#endif
-#if (_PERC_CHANGE_ == 50)
-    InvalidConfiguration;
-#endif
-#if (_PERC_STICKY_ && !_FOCUS_)
-    InvalidConfiguration;
-#endif
+#include"stopwatch.h"
 
+#include"sls_tactic.h"
 #include"sls_params.hpp"
-#include"sls_evaluator.h"
-#include"sls_tracker.h"
+#include"sls_engine.h"
 
-class sls_tactic : public tactic {
-    class stats {
-    public:
-        unsigned        m_restarts;
-        stopwatch       m_stopwatch;    
-        unsigned        m_full_evals;
-        unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
-
-        stats() :
-            m_restarts(0),
-            m_full_evals(0),
-            m_incr_evals(0),
-            m_moves(0),
-            m_umins(0),
-            m_mul2s(0),
-            m_mul3s(0),
-            m_div2s(0),
-            m_flips(0),
-            m_incs(0),
-            m_decs(0),
-            m_invs(0) {
-                m_stopwatch.reset();
-                m_stopwatch.start();
-            }
-        void reset() {
-            m_full_evals = m_flips = m_incr_evals = 0;
-            m_stopwatch.reset();
-            m_stopwatch.start();
-        }
-    };    
-
-    struct imp {       
-        ast_manager   & m_manager;
-        stats         & m_stats;
-        unsynch_mpz_manager m_mpz_manager;
-        powers          m_powers;
-        mpz             m_zero, m_one, m_two;            
-        bool            m_produce_models;
-        volatile bool   m_cancel;    
-        bv_util         m_bv_util;
-        sls_tracker     m_tracker;
-        sls_evaluator   m_evaluator;
-
-        unsigned		m_restart_limit;
-        unsigned        m_max_restarts;
-        unsigned        m_plateau_limit;
-
-        ptr_vector<mpz> m_old_values;
-        
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
-
-        imp(ast_manager & m, params_ref const & p, stats & s) : 
-            m_manager(m),
-            m_stats(s),
-            m_powers(m_mpz_manager),
-            m_zero(m_mpz_manager.mk_z(0)),
-            m_one(m_mpz_manager.mk_z(1)),
-            m_two(m_mpz_manager.mk_z(2)),
-            m_cancel(false),
-            m_bv_util(m),
-            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
-            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
-        {
-            updt_params(p);
-        }
-
-        ~imp() {
-            m_mpz_manager.del(m_zero);
-            m_mpz_manager.del(m_one);
-            m_mpz_manager.del(m_two);
-        }        
-
-        double get_restart_armin(unsigned cnt_restarts)
-        {
-            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-            //printf("armin: %f\n", pow(1.1, inner_id + 1));
-            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
-        }
-
-        inline unsigned check_restart(unsigned curr_value)
-        {
-            if (curr_value > m_restart_limit)
-            {
-#if _RESTART_SCHEME_ == 4
-                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
-#elif _RESTART_SCHEME_ == 3
-                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 2
-                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 1
-                if (m_stats.m_restarts & 1)
-                    m_restart_limit += _RESTART_LIMIT_;
-                else
-                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
-#else
-                    m_restart_limit += _RESTART_LIMIT_;
-#endif
-#if _WEIGHT_TOGGLE_
-                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-#endif
-                return 0;
-            }
-            return 1;
-        }
-
-        ast_manager & m() const { return m_manager; }
-
-        void set_cancel(bool f) { m_cancel = f; }
-        void cancel() { set_cancel(true); }
-        void reset_cancel() { set_cancel(false); }
-
-        static void collect_param_descrs(param_descrs & r) {
-            sls_params::collect_param_descrs(r);
-        }
-
-        void updt_params(params_ref const & _p) {
-            sls_params p(_p);
-            m_produce_models = _p.get_bool("model", false);
-            m_max_restarts = p.restarts();            
-            m_tracker.set_random_seed(p.random_seed());
-            m_plateau_limit = p.plateau_limit();
-        }
-
-        void checkpoint() { 
-            if (m_cancel)
-                throw tactic_exception(TACTIC_CANCELED_MSG);
-            cooperate("sls");
-        }
-
-        bool full_eval(goal_ref const & g, model & mdl) {
-            bool res = true;
-
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz && res; i++) {
-                checkpoint();
-                expr_ref o(m_manager);
-
-                if (!mdl.eval(g->form(i), o, true))
-                    exit(ERR_INTERNAL_FATAL);
-
-                res = m_manager.is_true(o.get());
-            }        
-
-            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
-
-            return res;
-        }
-
-        double top_score(goal_ref const & g) {
-            #if 0
-            double min = m_tracker.get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
-                double q = m_tracker.get_score(g->form(i));
-                if (q < min) min = q;
-            }
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                for (unsigned i = 0; i < sz; i++)
-                                    tout << " " << m_tracker.get_score(g->form(i));
-                                tout << " MIN: " << min << std::endl; );
-            return min;
-            #else
-            double top_sum = 0.0;
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                top_sum += m_tracker.get_score(e);
-            }
-
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                    for (unsigned i = 0; i < sz; i++)
-                                        tout << " " << m_tracker.get_score(g->form(i));
-                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
-
-#if _CACHE_TOP_SCORE_
-            m_tracker.set_top_sum(top_sum);
-#endif
-
-            return top_sum / (double) sz;
-            #endif
-        }
-
-        double rescore(goal_ref const & g) {
-            m_evaluator.update_all();
-            m_stats.m_full_evals++;
-            return top_score(g);
-        }
-
-        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.serious_update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-#if _EARLY_PRUNE_
-        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_stats.m_incr_evals++;
-            if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
-                return (m_tracker.get_top_sum() / g->size());
-#else
-                return top_score(g);
-#endif
-            else
-                return 0.0;
-        }
-#endif
-
-        // checks whether the score outcome of a given move is better than the previous score
-        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-
-            #ifdef Z3DEBUG
-            mpz old_value;
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-            #endif
-
-#if _EARLY_PRUNE_
-            double r = incremental_score_prune(g, fd, temp);
-#else
-            double r = incremental_score(g, fd, temp);
-#endif   
-            #ifdef Z3DEBUG
-            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
-                                        " --> " << r << std::endl; );
-        
-            m_mpz_manager.del(old_value);
-            #endif
-
-//            if (r >= best_score) {
-            if (r > best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // same as what_if, but only applied to the score of a specific atom, not the total score
-        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-            m_evaluator.update(fd, temp);
-            double r = m_tracker.get_score(e);
-            if (r >= best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.add(old_value, add_value, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-
-        }
-
-        // Andreas: do we really need all those temporary mpzs?
-        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.mul(old_value, m_two, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-        }
-
-        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            m_mpz_manager.div(old_value, m_two, result);
-        }
-
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
-            unsigned shift;        
-            m_mpz_manager.add(old_value, m_one, incremented);
-            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
-                m_mpz_manager.set(incremented, m_zero);
-        }
-
-        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
-            if (m_mpz_manager.is_zero(old_value)) {
-                m_mpz_manager.set(decremented, m_powers(bv_sz));
-                m_mpz_manager.dec(decremented);
-            }
-            else
-                m_mpz_manager.sub(old_value, m_one, decremented);
-        }
-
-        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
-            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
-        }
-
-        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
-            m_mpz_manager.set(flipped, m_zero);
-
-            if (m_bv_util.is_bv_sort(s)) {
-                mpz mask;
-                m_mpz_manager.set(mask, m_powers(bit));
-                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
-                m_mpz_manager.del(mask);
-            }
-            else if (m_manager.is_bool(s))
-                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
-            else
-                NOT_IMPLEMENTED_YET();
-        }
-
-        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
-        {
-            unsigned rnd_mv = 0;
-
-            unsigned ucc = unsat_constants.size(); 
-            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
-            func_decl * fd = unsat_constants[rc];
-
-            mpz new_value;
-
-            sort * srt = fd->get_range();
-            if (m_manager.is_bool(srt))
-                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-            else
-            {
-#if _USE_ADDSUB_
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-                move_type mt = (move_type) rnd_mv;
-
-                // inversion doesn't make sense, let's do a flip instead.
-                if (mt == MV_INV) mt = MV_FLIP;
-#else
-                mt = MV_FLIP;
-#endif
-                unsigned bit = 0;
-
-                switch (mt)
-                {
-                    case MV_FLIP: {
-                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
-                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                    break;
-                }
-                case MV_INC: 
-                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_DEC: 
-                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_INV:
-                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                default:
-                    NOT_IMPLEMENTED_YET();
-                }
-
-                TRACE("sls", tout << "Randomization candidates: ";
-                             for (unsigned i = 0; i < unsat_constants.size(); i++)
-                                 tout << unsat_constants[i]->get_name() << ", ";
-                             tout << std::endl;
-                             tout << "Random move: ";
-                             switch (mt) {
-                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                             }
-                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-            }
-
-            m_evaluator.update(fd, new_value);            
-            m_mpz_manager.del(new_value);
-        }
-
-        void mk_random_move(goal_ref const & g) {
-            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
-        }
-
-        // will use VNS to ignore some possible moves and increase the flips per second
-        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz, max_bv_sz = 0;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-                    // try to flip lsb
-                    mk_flip(srt, old_value, 0, temp);                
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = 0;
-                        move = MV_FLIP;
-                    }
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-
-            // we can either check the condition once in the beginning or check it repeatedly after every bit
-#if _VNS_ == 1
-            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
-#else
-            if (new_score <= score)
-            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
-#endif
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // What would happen if we flipped bit #j ?                
-                if (j < bv_sz)
-                {
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-            mpz temp2;
-#endif
-            unsigned bv_sz;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-#if _SKIP_BITS_
-                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
-#else
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-#endif
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-#endif
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-#if _USE_UNARY_MINUS_
-                    mk_inc(bv_sz, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_UMIN;
-#endif
-
-#if _USE_MUL2DIV2_
-                    // try multiplication by 2
-                    mk_mul2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_MUL2;
-
-#if _USE_MUL3_
-                    // try multiplication by 3
-                    mk_add(bv_sz, old_value, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_MUL3;
-#endif
-
-                    // try division by 2
-                    mk_div2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_DIV2;
-#endif
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                // Andreas: does not hold anymore now that we use top level score caching
-                //SASSERT(check == score);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-#if _USE_MUL3_
-            m_mpz_manager.del(temp2);
-#endif
-            return new_score;
-        }        
-
-        // same as find_best_move but only considers the score of the current expression instead of the overall score
-        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz;
-            double new_score = m_tracker.get_score(e);
-            // Andreas: tie breaking not implemented yet
-            // double tie_score = top_score(g);
-            for (unsigned i = 0; i < to_evaluate.size(); i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz; j++) {
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-                }
-
-                // reset to what it was before
-                m_evaluator.update(fd, old_value);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // first try of intensification ... does not seem to be efficient
-        bool handle_plateau(goal_ref const & g)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned pos = m_stats.m_moves % sz;
-#else
-            unsigned pos = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-            {
-                m_tracker.get_value(to_evaluate[i]);
-                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-            }            
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-            {
-                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
-                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    // Andreas: Actually this should never happen.
-                    NOT_IMPLEMENTED_YET();
-                } else {
-                    m_stats.m_moves++;
-                    func_decl * fd = to_evaluate[new_const];
-
-                    switch (move) {
-                    case MV_FLIP: m_stats.m_flips++; break;
-                    case MV_INC: m_stats.m_incs++; break;
-                    case MV_DEC: m_stats.m_decs++; break;
-                    case MV_INV: m_stats.m_invs++; break;
-                    case MV_UMIN: m_stats.m_umins++; break;
-                    case MV_MUL2: m_stats.m_mul2s++; break;
-                    case MV_MUL3: m_stats.m_mul3s++; break;
-                    case MV_DIV2: m_stats.m_div2s++; break;
-                    }
-                    
-                    m_evaluator.update(fd, new_value);
-                }
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
-
-            m_old_values.reset();
-
-            return 0;
-        }
-
-        // what_if version needed in the context of 2nd intensification try, combining local and global score
-        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
-                        double & best_score, mpz & best_value, unsigned i) {
-        
-            double global_score = incremental_score(g, fd, temp);
-            double local_score = m_tracker.get_score(e);
-            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
-
-            if (new_score >= best_score) {
-                best_score = new_score;
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // find_best_move version needed in the context of 2nd intensification try
-        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-        {
-            mpz old_value, temp;
-            double best_score = 0;
-
-            sort * srt = fd->get_range();
-            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
-                mk_flip(srt, old_value, j, temp);                
-                what_if(g, e, fd, temp, best_score, best_value, i); 
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-
-            return best_score;
-        }        
-
-        // second try to use intensification ... also not very effective
-        bool handle_plateau(goal_ref const & g, double old_score)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned new_const = m_stats.m_moves % sz;
-#else
-            unsigned new_const = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-
-            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-            func_decl * fd = to_evaluate[new_const];
-
-            mpz new_value;
-            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-            unsigned new_bit = 0;        
-            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-            
-            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-            {
-                new_score = find_best_move_local(g, q, fd, new_value, i);
-
-                m_stats.m_moves++;
-                m_stats.m_flips++;
-
-                global_score = incremental_score(g, fd, new_value);
-                local_score = m_tracker.get_score(q);
-
-                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            return 0;
-        }
-
-        // main search loop
-        lbool search(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            unsigned plateau_cnt = 0;
-
-            score = rescore(g);
-            unsigned sz = g->size();
-#if _PERC_STICKY_
-            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-
-#if _RESTARTS_ == 1
-            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 2
-            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 3
-            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#endif
-                checkpoint();
-                m_stats.m_moves++;
-
-#if _REAL_RS_ || _REAL_PBFS_
-                //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
-
-#if _FOCUS_
-#if _PERC_STICKY_
-                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
-                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#else
-                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-                if (!e)
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
-                if (!to_evaluate.size())
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-#endif
-
-#if _TYPE_RSTEP_
-                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                {
-#if _TYPE_RSTEP_ == 1
-                    m_evaluator.randomize_local(to_evaluate);
-#elif _TYPE_RSTEP_ == 2
-                    mk_random_move(to_evaluate);
-#endif
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                }
-                continue;
-#endif
-
-#if _WEIGHT_DIST_ == 4
-                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif       
-                old_score = score;
-                new_const = (unsigned)-1;
-
-#if _VNS_
-                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    score = old_score;
-                    plateau_cnt++;
-#if _INTENSIFICATION_
-                    handle_plateau(g, score);
-                    //handle_plateau(g);
-                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-#if _PERC_PLATEAU_MOVES_
-                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
-                        mk_random_move(to_evaluate);
-                    else
-#endif
-#if _REPICK_
-                    m_evaluator.randomize_local(g, m_stats.m_moves);
-#else
-                    m_evaluator.randomize_local(to_evaluate);
-#endif
-#endif
-
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                } else {
-                    func_decl * fd = to_evaluate[new_const];              
-#if _REAL_RS_ || _REAL_PBFS_
-                    score = serious_score(g, fd, new_value);
-#else
-                    score = incremental_score(g, fd, new_value);    
-#endif
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        // main search loop
-        lbool search_old(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            
-            score = rescore(g);
-            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-                         tout << "Score distribution:"; 
-                         for (unsigned i = 0; i < g->size(); i++)
-                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                         tout << " TOP: " << score << std::endl; ); 
-        
-            unsigned plateau_cnt = 0;
-
-            // Andreas: Why do we only allow so few plateaus?
-#if _RESTARTS_
-            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
-            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
-#endif
-                do {
-                    checkpoint();
-
-#if _WEIGHT_DIST_ == 4
-                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-            
-#if _TYPE_RSTEP_
-                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                    {
-#if _TYPE_RSTEP_ == 1
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _TYPE_RSTEP_ == 2
-                        mk_random_move(g);
-#endif
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                            } else
-                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                        }
-                    }
-#endif
-                    old_score = score;
-                    new_const = (unsigned)-1;
-                        
-                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-                    if (!to_evaluate.size())
-                    {
-                        res = l_true;
-                        goto bailout;
-                    }
-                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
-                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
-                                                tout << to_evaluate[i]->get_name() << std::endl; );
-
-#if _VNS_
-                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-                    if (new_const == static_cast<unsigned>(-1)) {
-                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
-                                        for (unsigned i = 0; i < g->size(); i++) {
-                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
-                                        });
-
-                        TRACE("sls_max", m_tracker.show_model(tout);
-                                        tout << "Scores: " << std::endl;
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
-                                            m_tracker.get_score(g->form(i)) << std::endl; );
-                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
-                        score = old_score;
-                    }
-                    else {
-                        // Andreas: Why does randomizing not count as a move? (Now it does.)
-                        m_stats.m_moves++;
-                        func_decl * fd = to_evaluate[new_const];
-
-                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
-                                        switch (move) {
-                                        case MV_FLIP:  
-                                            tout << "Flip";
-                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
-                                            break;
-                                        case MV_INC: 
-                                            tout << "+1";
-                                            break;
-                                        case MV_DEC: 
-                                            tout << "-1";
-                                            break;
-                                        case MV_INV: 
-                                            tout << "NEG";
-                                            break;
-                                        };                                        
-                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
-
-                        switch (move) {
-                        case MV_FLIP: m_stats.m_flips++; break;
-                        case MV_INC: m_stats.m_incs++; break;
-                        case MV_DEC: m_stats.m_decs++; break;
-                        case MV_INV: m_stats.m_invs++; break;
-                        case MV_UMIN: m_stats.m_umins++; break;
-                        case MV_MUL2: m_stats.m_mul2s++; break;
-                        case MV_MUL3: m_stats.m_mul3s++; break;
-                        case MV_DIV2: m_stats.m_div2s++; break;
-                        }
-                    
-#if _REAL_RS_ || _REAL_PBFS_
-                        score = serious_score(g, fd, new_value);
-#else
-                        score = incremental_score(g, fd, new_value);    
-#endif
-
-                        TRACE("sls", tout << "Score distribution:"; 
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                                        tout << " TOP: " << score << std::endl; );                        
-                    }
-
-                    if (score >= 0.99999) {
-//                    if (score >= 1.0) {
-                        // score could theoretically be imprecise.
-                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
-                        bool all_true = true;
-                        for (unsigned i = 0; i < g->size() && all_true; i++)
-                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                all_true=false;
-                        if (all_true) {
-                            res = l_true; // sat
-                            goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                    /*
-                    if (m_stats.m_moves % 100 == 0)
-                    {
-                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-                    }*/
-                }
-                while (score > old_score && res == l_undef);                
-                
-                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
-                if (score != old_score) {
-                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
-                    plateau_cnt = 0;
-                } else {
-                    m_stats.m_moves++;
-                    plateau_cnt++;
-                    //report_tactic_progress("Plateau.", plateau_cnt);
-                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
-                    //if (plateau_cnt < m_plateau_limit) {
-                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
-#if _INTENSIFICATION_
-                        handle_plateau(g, score);
-                        //handle_plateau(g);
-#else
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#endif
-                        //mk_random_move(g);
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        void operator()(goal_ref const & g, model_converter_ref & mc) {
-            if (g->inconsistent()) {
-                mc = 0;
-                return;
-            }
-
-            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
-            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
-            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
-            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
-            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-            
-#if _WEIGHT_DIST_ == 4
-            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-            m_tracker.initialize(g);
-            lbool res = l_undef;
-        
-            m_restart_limit = _RESTART_LIMIT_;
-
-            do {
-                checkpoint();
-
-                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                res = search(g);
-
-                if (res == l_undef)
-                {
-#if _RESTART_INIT_
-                    m_tracker.randomize(g);
-#else
-                    m_tracker.reset(g);
-#endif
-                }
-            }
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-        
-            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-            if (res == l_true) {    
-                report_tactic_progress("Number of flips:", m_stats.m_moves);
-                for (unsigned i = 0; i < g->size(); i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                    {
-                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                        NOT_IMPLEMENTED_YET(); 
-                    }
-
-                if (m_produce_models) {
-                    model_ref mdl = m_tracker.get_model();
-                    mc = model2model_converter(mdl.get());
-                    TRACE("sls_model", mc->display(tout); );
-                }
-                g->reset();
-            }
-            else
-                mc = 0;
-        }
-    };
-    
+class sls_tactic : public tactic {    
     ast_manager    & m;
     params_ref       m_params;
-    imp            * m_imp;
-    stats            m_stats;
+    sls_engine     * m_engine;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_imp = alloc(imp, m, p, m_stats);
+        m_engine = alloc(sls_engine, m, p);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -1381,16 +48,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_imp);
+        dealloc(m_engine);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_imp->updt_params(p);
+        m_engine->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        imp::collect_param_descrs(r);
+        sls_params::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -1398,14 +65,13 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());
-        m_imp->m_produce_models = g->models_enabled();        
+        SASSERT(g->is_well_sorted());        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_imp->operator()(g, mc);
+        m_engine->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -1414,40 +80,41 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = m_imp;
+        sls_engine * d = m_engine;
         #pragma omp critical (tactic_cancel)
         {
-            d = m_imp;
+            d = m_engine;
         }
         dealloc(d);
-        d = alloc(imp, m, m_params, m_stats);
+        d = alloc(sls_engine, m, m_params);
         #pragma omp critical (tactic_cancel) 
         {
-            m_imp = d;
+            m_engine = d;
         }
     }
     
     virtual void collect_statistics(statistics & st) const {
-        double seconds = m_stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", m_stats.m_restarts);
-        st.update("sls full evals", m_stats.m_full_evals);
-        st.update("sls incr evals", m_stats.m_incr_evals);
-        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
-        st.update("sls FLIP moves", m_stats.m_flips);    
-        st.update("sls INC moves", m_stats.m_incs);
-        st.update("sls DEC moves", m_stats.m_decs);
-        st.update("sls INV moves", m_stats.m_invs);
-        st.update("sls moves", m_stats.m_moves);
-        st.update("sls moves/sec", m_stats.m_moves / seconds);
+        sls_engine::stats const & stats = m_engine->get_stats();
+        double seconds = stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", stats.m_restarts);
+        st.update("sls full evals", stats.m_full_evals);
+        st.update("sls incr evals", stats.m_incr_evals);
+        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
+        st.update("sls FLIP moves", stats.m_flips);
+        st.update("sls INC moves", stats.m_incs);
+        st.update("sls DEC moves", stats.m_decs);
+        st.update("sls INV moves", stats.m_invs);
+        st.update("sls moves", stats.m_moves);
+        st.update("sls moves/sec", stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_stats.reset();
+        m_engine->reset_statistics();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_imp)
-            m_imp->set_cancel(f);
+        if (m_engine)
+            m_engine->set_cancel(f);
     }
 };
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 0aca1f59c..3675265ee 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,6 +20,12 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
+#include"goal.h"
+#include"model.h"
+
+#include"sls_compilation_settings.h"
+#include"sls_powers.h"
+
 class sls_tracker {
     ast_manager         & m_manager;
     unsynch_mpz_manager & m_mpz_manager;
@@ -1186,7 +1192,7 @@ public:
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); 
 #elif _UCT_ == 2
                 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif
@@ -1334,7 +1340,7 @@ public:
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched); 
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #endif

From 13307a1d51c1c21e421b6a1e28fc8b5476f7b53e Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 19 Mar 2014 17:26:05 +0000
Subject: [PATCH 072/108] SLS refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index aea4787b0..8e52596e0 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -18,6 +18,10 @@ Notes:
     This file should go away completely once we have evaluated all options.
 
 --*/
+
+#ifndef _SLS_COMPILATION_SETTINGS_H_
+#define _SLS_COMPILATION_SETTINGS_H_
+
 // which unsatisfied assertion is selected? only works with _FOCUS_ > 0
 // 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
 #define _BFS_ 0
@@ -155,4 +159,6 @@ InvalidConfiguration;
 #endif
 #if (_PERC_STICKY_ && !_FOCUS_)
 InvalidConfiguration;
+#endif
+
 #endif
\ No newline at end of file

From ad8cac7d886d1dc6e9255990fc192c83662c2277 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Thu, 20 Mar 2014 15:58:53 +0000
Subject: [PATCH 073/108] uct forget and minisat restarts added

---
 src/tactic/sls/sls_tactic.cpp | 1417 ++++++++++++++++++++++++++++++++-
 src/tactic/sls/sls_tracker.h  |   22 +-
 2 files changed, 1402 insertions(+), 37 deletions(-)

diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 0f157d3a6..b2b7035e0 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,31 +16,1378 @@ Author:
 Notes:
 
 --*/
+#include<iomanip>
+#include"map.h"
 #include"nnf.h"
+#include"cooperate.h"
+#include"ast_smt2_pp.h"
+#include"ast_pp.h"
+#include"var_subst.h"
+#include"model_pp.h"
+#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"propagate_values_tactic.h"
-#include"ctx_simplify_tactic.h"
-#include"elim_uncnstr_tactic.h"
-#include"nnf_tactic.h"
 #include"stopwatch.h"
-
+#include"propagate_values_tactic.h"
 #include"sls_tactic.h"
-#include"sls_params.hpp"
-#include"sls_engine.h"
+#include"nnf_tactic.h"
+#include"luby.h"
+#include "ctx_simplify_tactic.h"
 
-class sls_tactic : public tactic {    
+// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
+// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
+#define _BFS_ 0
+
+// how many terms are considered for variable selection?
+// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
+#define _FOCUS_ 1
+
+// probability of choosing the same assertion again in the next step
+#define _PERC_STICKY_ 0
+
+// do we use dirty unit propagation to get rid of nested top level assertions?
+#define _DIRTY_UP_ 1
+
+// do we use restarts?
+// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
+#define _RESTARTS_ 3
+// limit of moves/plateaus/seconds until first restart occurs
+#define _RESTART_LIMIT_ 10
+// 0 = initialize with all zero, 1 initialize with random value
+#define _RESTART_INIT_ 0
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
+#define _RESTART_SCHEME_ 1
+// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
+#define _RESTART_CONST_ARMIN_ 4.0
+
+// timelimit
+#define _TIMELIMIT_ 3600
+
+// should score of conjunctions be calculated by average rather than max?
+#define _SCORE_AND_AVG_ 0
+
+// should score of discunctions be calculated by multiplication of the inverse score rather than min?
+#define _SCORE_OR_MUL_ 0
+
+// do we use some kind of variable neighbourhood-search?
+// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
+#define _VNS_ 0
+
+// do we reduce the score of unsatisfied literals?
+// 0 = no
+// 1 = yes, by multiplying it with some factor
+// 2 = yes, by squaring it
+// 3 = yes, by setting it to zero
+// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
+#define _WEIGHT_DIST_ 1
+
+// the factor used for _WEIGHT_DIST_ = 1
+#define _WEIGHT_DIST_FACTOR_ 0.5
+
+// shall we toggle the weight after each restart?
+#define _WEIGHT_TOGGLE_ 0
+
+// do we use intensification steps in local minima? if so, how many?
+#define _INTENSIFICATION_ 0
+#define _INTENSIFICATION_TRIES_ 0
+
+// what is the percentage of random moves in plateaus (instead of full randomization)?
+#define _PERC_PLATEAU_MOVES_ 0
+
+// shall we repick clause when randomizing in a plateau or use the current one?
+#define _REPICK_ 1
+
+// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
+#define _UCT_ 1
+
+// how much diversification is used in the UCT-scheme?
+#define _UCT_CONSTANT_ 20.0
+
+// is uct clause selection probabilistic similar to variable selection in sparrow?
+// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
+#define _PROBABILISTIC_UCT_ 0
+
+// additive constants for probabilistic uct > 0
+#define _UCT_EPS_ 0.0001
+
+// shall we reset _UCT_ touched values after restart?
+#define _UCT_RESET_ 0
+
+// do we gradually reduce the touched values of _UCT_?
+#define _UCT_FORGET_ 0
+#define _UCT_FORGET_FACTOR_ 0.5
+
+// how shall we initialize the _UCT_ total touched counter?
+// 0 = initialize with one, 1 = initialize with number of assertions
+#define _UCT_INIT_ 0
+
+// shall we use addition/subtraction?
+#define _USE_ADDSUB_ 1
+
+// shall we try multilication and division by 2?
+#define _USE_MUL2DIV2_ 0
+
+// shall we try multiplication by 3?
+#define _USE_MUL3_ 0
+
+// shall we try unary minus (= inverting and incrementing)
+#define _USE_UNARY_MINUS_ 0
+
+// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
+#define _UNIFORM_RANDOM_ 0
+
+// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+#define _REAL_RS_ 0
+#define _REAL_PBFS_ 0
+
+// how many bits do we neglect in each iteration?
+#define _SKIP_BITS_ 0
+
+// when randomizing local, what is the probability for changing a single bit?
+// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
+#define _PERC_CHANGE_ 0
+
+// do we use random steps for noise?
+// 0 = no, 1 = randomize local, 2 = make random move
+#define _TYPE_RSTEP_ 0
+
+// with what probability _PERM_STEP_/1000 will the random step happen? 
+#define _PERM_RSTEP_ 0
+
+// shall we use early pruning for incremental update?
+#define _EARLY_PRUNE_ 1
+
+// shall we use caching for top_score?
+#define _CACHE_TOP_SCORE_ 1
+
+
+#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
+    InvalidConfiguration;
+#endif
+#if (_PROBABILISTIC_UCT_ && !_UCT_)
+    InvalidConfiguration;
+#endif
+#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
+    InvalidConfiguration;
+#endif
+#if (_PERC_CHANGE_ == 50)
+    InvalidConfiguration;
+#endif
+#if (_PERC_STICKY_ && !_FOCUS_)
+    InvalidConfiguration;
+#endif
+
+#include"sls_params.hpp"
+#include"sls_evaluator.h"
+#include"sls_tracker.h"
+
+class sls_tactic : public tactic {
+    class stats {
+    public:
+        unsigned        m_restarts;
+        stopwatch       m_stopwatch;    
+        unsigned        m_full_evals;
+        unsigned        m_incr_evals;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+
+        stats() :
+            m_restarts(0),
+            m_full_evals(0),
+            m_incr_evals(0),
+            m_moves(0),
+            m_umins(0),
+            m_mul2s(0),
+            m_mul3s(0),
+            m_div2s(0),
+            m_flips(0),
+            m_incs(0),
+            m_decs(0),
+            m_invs(0) {
+                m_stopwatch.reset();
+                m_stopwatch.start();
+            }
+        void reset() {
+            m_full_evals = m_flips = m_incr_evals = 0;
+            m_stopwatch.reset();
+            m_stopwatch.start();
+        }
+    };    
+
+    struct imp {       
+        ast_manager   & m_manager;
+        stats         & m_stats;
+        unsynch_mpz_manager m_mpz_manager;
+        powers          m_powers;
+        mpz             m_zero, m_one, m_two;            
+        bool            m_produce_models;
+        volatile bool   m_cancel;    
+        bv_util         m_bv_util;
+        sls_tracker     m_tracker;
+        sls_evaluator   m_evaluator;
+
+        unsigned		m_restart_limit;
+        unsigned        m_max_restarts;
+        unsigned        m_plateau_limit;
+
+        ptr_vector<mpz> m_old_values;
+        
+        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
+
+        imp(ast_manager & m, params_ref const & p, stats & s) : 
+            m_manager(m),
+            m_stats(s),
+            m_powers(m_mpz_manager),
+            m_zero(m_mpz_manager.mk_z(0)),
+            m_one(m_mpz_manager.mk_z(1)),
+            m_two(m_mpz_manager.mk_z(2)),
+            m_cancel(false),
+            m_bv_util(m),
+            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
+            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
+        {
+            updt_params(p);
+        }
+
+        ~imp() {
+            m_mpz_manager.del(m_zero);
+            m_mpz_manager.del(m_one);
+            m_mpz_manager.del(m_two);
+        }        
+
+        double get_restart_armin(unsigned cnt_restarts)
+        {
+            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+            //printf("armin: %f\n", pow(1.1, inner_id + 1));
+            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
+        }
+
+        inline unsigned check_restart(unsigned curr_value)
+        {
+            if (curr_value > m_restart_limit)
+            {
+#if _RESTART_SCHEME_ == 5
+                m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+#elif _RESTART_SCHEME_ == 4
+                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+#elif _RESTART_SCHEME_ == 3
+                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 2
+                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+#elif _RESTART_SCHEME_ == 1
+                if (m_stats.m_restarts & 1)
+                    m_restart_limit += _RESTART_LIMIT_;
+                else
+                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+#else
+                    m_restart_limit += _RESTART_LIMIT_;
+#endif
+#if _WEIGHT_TOGGLE_
+                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
+#endif
+                return 0;
+            }
+            return 1;
+        }
+
+        ast_manager & m() const { return m_manager; }
+
+        void set_cancel(bool f) { m_cancel = f; }
+        void cancel() { set_cancel(true); }
+        void reset_cancel() { set_cancel(false); }
+
+        static void collect_param_descrs(param_descrs & r) {
+            sls_params::collect_param_descrs(r);
+        }
+
+        void updt_params(params_ref const & _p) {
+            sls_params p(_p);
+            m_produce_models = _p.get_bool("model", false);
+            m_max_restarts = p.restarts();            
+            m_tracker.set_random_seed(p.random_seed());
+            m_plateau_limit = p.plateau_limit();
+        }
+
+        void checkpoint() { 
+            if (m_cancel)
+                throw tactic_exception(TACTIC_CANCELED_MSG);
+            cooperate("sls");
+        }
+
+        bool full_eval(goal_ref const & g, model & mdl) {
+            bool res = true;
+
+            unsigned sz = g->size();
+            for (unsigned i = 0; i < sz && res; i++) {
+                checkpoint();
+                expr_ref o(m_manager);
+
+                if (!mdl.eval(g->form(i), o, true))
+                    exit(ERR_INTERNAL_FATAL);
+
+                res = m_manager.is_true(o.get());
+            }        
+
+            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
+
+            return res;
+        }
+
+        double top_score(goal_ref const & g) {
+            #if 0
+            double min = m_tracker.get_score(g->form(0));
+            unsigned sz = g->size();
+            for (unsigned i = 1; i < sz; i++) {
+                double q = m_tracker.get_score(g->form(i));
+                if (q < min) min = q;
+            }
+            TRACE("sls_top", tout << "Score distribution:"; 
+                                for (unsigned i = 0; i < sz; i++)
+                                    tout << " " << m_tracker.get_score(g->form(i));
+                                tout << " MIN: " << min << std::endl; );
+            return min;
+            #else
+            double top_sum = 0.0;
+            unsigned sz = g->size();
+            for (unsigned i = 0; i < sz; i++) {
+                expr * e = g->form(i);
+                top_sum += m_tracker.get_score(e);
+            }
+
+            TRACE("sls_top", tout << "Score distribution:"; 
+                                    for (unsigned i = 0; i < sz; i++)
+                                        tout << " " << m_tracker.get_score(g->form(i));
+                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
+
+#if _CACHE_TOP_SCORE_
+            m_tracker.set_top_sum(top_sum);
+#endif
+
+            return top_sum / (double) sz;
+            #endif
+        }
+
+        double rescore(goal_ref const & g) {
+            m_evaluator.update_all();
+            m_stats.m_full_evals++;
+            return top_score(g);
+        }
+
+        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_evaluator.serious_update(fd, new_value);
+            m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+            return (m_tracker.get_top_sum() / g->size());
+#else
+            return top_score(g);
+#endif
+        }
+
+        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_evaluator.update(fd, new_value);
+            m_stats.m_incr_evals++;
+#if _CACHE_TOP_SCORE_
+            return (m_tracker.get_top_sum() / g->size());
+#else
+            return top_score(g);
+#endif
+        }
+
+#if _EARLY_PRUNE_
+        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+            m_stats.m_incr_evals++;
+            if (m_evaluator.update_prune(fd, new_value))
+#if _CACHE_TOP_SCORE_
+                return (m_tracker.get_top_sum() / g->size());
+#else
+                return top_score(g);
+#endif
+            else
+                return 0.0;
+        }
+#endif
+
+        // checks whether the score outcome of a given move is better than the previous score
+        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+
+            #ifdef Z3DEBUG
+            mpz old_value;
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+            #endif
+
+#if _EARLY_PRUNE_
+            double r = incremental_score_prune(g, fd, temp);
+#else
+            double r = incremental_score(g, fd, temp);
+#endif   
+            #ifdef Z3DEBUG
+            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
+                                        " --> " << r << std::endl; );
+        
+            m_mpz_manager.del(old_value);
+            #endif
+
+//            if (r >= best_score) {
+            if (r > best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+        // same as what_if, but only applied to the score of a specific atom, not the total score
+        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
+                        double & best_score, unsigned & best_const, mpz & best_value) {
+            m_evaluator.update(fd, temp);
+            double r = m_tracker.get_score(e);
+            if (r >= best_score) {
+                best_score = r;
+                best_const = fd_inx;            
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.add(old_value, add_value, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
+
+        }
+
+        // Andreas: do we really need all those temporary mpzs?
+        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            mpz temp, mask, mask2;
+            m_mpz_manager.mul(old_value, m_two, temp);
+            m_mpz_manager.set(mask, m_powers(bv_sz));
+            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
+            m_mpz_manager.bitwise_and(temp, mask2, result);
+            m_mpz_manager.del(temp);
+            m_mpz_manager.del(mask);
+            m_mpz_manager.del(mask2);
+        }
+
+        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
+            m_mpz_manager.div(old_value, m_two, result);
+        }
+
+        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
+            unsigned shift;        
+            m_mpz_manager.add(old_value, m_one, incremented);
+            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
+                m_mpz_manager.set(incremented, m_zero);
+        }
+
+        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
+            if (m_mpz_manager.is_zero(old_value)) {
+                m_mpz_manager.set(decremented, m_powers(bv_sz));
+                m_mpz_manager.dec(decremented);
+            }
+            else
+                m_mpz_manager.sub(old_value, m_one, decremented);
+        }
+
+        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
+            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
+        }
+
+        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
+            m_mpz_manager.set(flipped, m_zero);
+
+            if (m_bv_util.is_bv_sort(s)) {
+                mpz mask;
+                m_mpz_manager.set(mask, m_powers(bit));
+                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
+                m_mpz_manager.del(mask);
+            }
+            else if (m_manager.is_bool(s))
+                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
+            else
+                NOT_IMPLEMENTED_YET();
+        }
+
+        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
+        {
+            unsigned rnd_mv = 0;
+            unsigned ucc = unsat_constants.size(); 
+            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
+            func_decl * fd = unsat_constants[rc];
+
+            mpz new_value;
+
+            sort * srt = fd->get_range();
+            if (m_manager.is_bool(srt))
+                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
+            else
+            {
+#if _USE_ADDSUB_
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
+                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+                move_type mt = (move_type) rnd_mv;
+
+                // inversion doesn't make sense, let's do a flip instead.
+                if (mt == MV_INV) mt = MV_FLIP;
+#else
+                mt = MV_FLIP;
+#endif
+                unsigned bit = 0;
+
+                switch (mt)
+                {
+                    case MV_FLIP: {
+                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
+                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
+                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
+                    break;
+                }
+                case MV_INC: 
+                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_DEC: 
+                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                case MV_INV:
+                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
+                    break;
+                default:
+                    NOT_IMPLEMENTED_YET();
+                }
+
+                TRACE("sls", tout << "Randomization candidates: ";
+                             for (unsigned i = 0; i < unsat_constants.size(); i++)
+                                 tout << unsat_constants[i]->get_name() << ", ";
+                             tout << std::endl;
+                             tout << "Random move: ";
+                             switch (mt) {
+                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
+                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
+                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
+                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
+                             }
+                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
+            }
+
+            m_evaluator.update(fd, new_value);            
+            m_mpz_manager.del(new_value);
+        }
+
+        void mk_random_move(goal_ref const & g) {
+            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
+        }
+
+        // will use VNS to ignore some possible moves and increase the flips per second
+        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz, max_bv_sz = 0;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+
+                    // try to flip lsb
+                    mk_flip(srt, old_value, 0, temp);                
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = 0;
+                        move = MV_FLIP;
+                    }
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+
+            // we can either check the condition once in the beginning or check it repeatedly after every bit
+#if _VNS_ == 1
+            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
+#else
+            if (new_score <= score)
+            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
+#endif
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // What would happen if we flipped bit #j ?                
+                if (j < bv_sz)
+                {
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                SASSERT(check == score);
+            }
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
+        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+#if _USE_MUL3_ || _USE_UNARY_MINUS_
+            mpz temp2;
+#endif
+            unsigned bv_sz;
+            double new_score = score;
+
+            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+#if _SKIP_BITS_
+                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
+#else
+                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+#endif
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+#if _USE_ADDSUB_
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+#endif
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+
+#if _USE_UNARY_MINUS_
+                    mk_inc(bv_sz, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_UMIN;
+#endif
+
+#if _USE_MUL2DIV2_
+                    // try multiplication by 2
+                    mk_mul2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_MUL2;
+
+#if _USE_MUL3_
+                    // try multiplication by 3
+                    mk_add(bv_sz, old_value, temp, temp2);
+                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
+                        move = MV_MUL3;
+#endif
+
+                    // try division by 2
+                    mk_div2(bv_sz, old_value, temp);
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_DIV2;
+#endif
+                }
+
+                // reset to what it was before
+                double check = incremental_score(g, fd, old_value);
+                // Andreas: does not hold anymore now that we use top level score caching
+                //SASSERT(check == score);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+#if _USE_MUL3_
+            m_mpz_manager.del(temp2);
+#endif
+            return new_score;
+        }        
+
+        // same as find_best_move but only considers the score of the current expression instead of the overall score
+        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+            mpz old_value, temp;
+            unsigned bv_sz;
+            double new_score = m_tracker.get_score(e);
+            // Andreas: tie breaking not implemented yet
+            // double tie_score = top_score(g);
+            for (unsigned i = 0; i < to_evaluate.size(); i++) {
+                func_decl * fd = to_evaluate[i];
+                sort * srt = fd->get_range();
+                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+                // first try to flip every bit
+                for (unsigned j = 0; j < bv_sz; j++) {
+                    // What would happen if we flipped bit #i ?                
+                    mk_flip(srt, old_value, j, temp);                
+
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
+                        new_bit = j;
+                        move = MV_FLIP;
+                    }
+                }
+
+                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+                    if (!m_mpz_manager.is_even(old_value)) { 
+                        // for odd values, try +1
+                        mk_inc(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_INC;
+                    }
+                    else { 
+                        // for even values, try -1
+                        mk_dec(bv_sz, old_value, temp);
+                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                            move = MV_DEC;
+                    }
+
+                    // try inverting
+                    mk_inv(bv_sz, old_value, temp);
+                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
+                        move = MV_INV;
+                }
+
+                // reset to what it was before
+                m_evaluator.update(fd, old_value);
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+            return new_score;
+        }        
+
+        // first try of intensification ... does not seem to be efficient
+        bool handle_plateau(goal_ref const & g)
+        {
+            unsigned sz = g->size();
+#if _BFS_
+            unsigned pos = m_stats.m_moves % sz;
+#else
+            unsigned pos = m_tracker.get_random_uint(16) % sz;
+#endif
+            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+            if (!e)
+                return 0;
+
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+            {
+                m_tracker.get_value(to_evaluate[i]);
+                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
+            }            
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
+            {
+                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
+                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
+
+                if (new_const == static_cast<unsigned>(-1)) {
+                    // Andreas: Actually this should never happen.
+                    NOT_IMPLEMENTED_YET();
+                } else {
+                    m_stats.m_moves++;
+                    func_decl * fd = to_evaluate[new_const];
+
+                    switch (move) {
+                    case MV_FLIP: m_stats.m_flips++; break;
+                    case MV_INC: m_stats.m_incs++; break;
+                    case MV_DEC: m_stats.m_decs++; break;
+                    case MV_INV: m_stats.m_invs++; break;
+                    case MV_UMIN: m_stats.m_umins++; break;
+                    case MV_MUL2: m_stats.m_mul2s++; break;
+                    case MV_MUL3: m_stats.m_mul3s++; break;
+                    case MV_DIV2: m_stats.m_div2s++; break;
+                    }
+                    
+                    m_evaluator.update(fd, new_value);
+                }
+
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
+
+            for (unsigned i = 0; i < to_evaluate.size(); i++)
+                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
+
+            m_old_values.reset();
+
+            return 0;
+        }
+
+        // what_if version needed in the context of 2nd intensification try, combining local and global score
+        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
+                        double & best_score, mpz & best_value, unsigned i) {
+        
+            double global_score = incremental_score(g, fd, temp);
+            double local_score = m_tracker.get_score(e);
+            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
+
+            if (new_score >= best_score) {
+                best_score = new_score;
+                m_mpz_manager.set(best_value, temp);
+                return true;
+            }
+
+            return false;
+        }
+
+        // find_best_move version needed in the context of 2nd intensification try
+        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+        {
+            mpz old_value, temp;
+            double best_score = 0;
+
+            sort * srt = fd->get_range();
+            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
+                mk_flip(srt, old_value, j, temp);                
+                what_if(g, e, fd, temp, best_score, best_value, i); 
+            }
+
+            m_mpz_manager.del(old_value);
+            m_mpz_manager.del(temp);
+
+            return best_score;
+        }        
+
+        // second try to use intensification ... also not very effective
+        bool handle_plateau(goal_ref const & g, double old_score)
+        {
+            unsigned sz = g->size();
+#if _BFS_
+            unsigned new_const = m_stats.m_moves % sz;
+#else
+            unsigned new_const = m_tracker.get_random_uint(16) % sz;
+#endif
+            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+            if (!e)
+                return 0;
+
+            expr * q = m_tracker.get_unsat_expression(e);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
+
+            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
+            func_decl * fd = to_evaluate[new_const];
+
+            mpz new_value;
+            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
+            unsigned new_bit = 0;        
+            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
+            
+            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
+            {
+                new_score = find_best_move_local(g, q, fd, new_value, i);
+
+                m_stats.m_moves++;
+                m_stats.m_flips++;
+
+                global_score = incremental_score(g, fd, new_value);
+                local_score = m_tracker.get_score(q);
+
+                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
+
+                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
+                    return 1;
+            }
+
+            return 0;
+        }
+
+        // main search loop
+        lbool search(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            unsigned plateau_cnt = 0;
+
+            score = rescore(g);
+            unsigned sz = g->size();
+#if _PERC_STICKY_
+            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+
+#if _RESTARTS_ == 1
+            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 2
+            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#elif _RESTARTS_ == 3
+            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#endif
+                checkpoint();
+                m_stats.m_moves++;
+
+#if _UCT_FORGET_
+                if (m_stats.m_moves % _UCT_FORGET_ == 0)
+                    m_tracker.uct_forget(g);
+#endif
+
+#if _REAL_RS_ || _REAL_PBFS_
+                //m_tracker.debug_real(g, m_stats.m_moves);
+#endif
+
+#if _FOCUS_
+#if _PERC_STICKY_
+                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
+                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#else
+                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+#endif
+                if (!e)
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+                if (!to_evaluate.size())
+                {
+                    res = l_true;
+                    goto bailout;
+                }
+#endif
+
+#if _TYPE_RSTEP_
+                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                {
+#if _TYPE_RSTEP_ == 1
+                    m_evaluator.randomize_local(to_evaluate);
+#elif _TYPE_RSTEP_ == 2
+                    mk_random_move(to_evaluate);
+#endif
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                }
+                continue;
+#endif
+
+#if _WEIGHT_DIST_ == 4
+                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif       
+                old_score = score;
+                new_const = (unsigned)-1;
+
+#if _VNS_
+                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+
+                if (new_const == static_cast<unsigned>(-1)) {
+                    score = old_score;
+                    plateau_cnt++;
+#if _INTENSIFICATION_
+                    handle_plateau(g, score);
+                    //handle_plateau(g);
+                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
+                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
+#else
+#if _PERC_PLATEAU_MOVES_
+                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
+                        mk_random_move(to_evaluate);
+                    else
+#endif
+#if _REPICK_
+                    m_evaluator.randomize_local(g, m_stats.m_moves);
+#else
+                    m_evaluator.randomize_local(to_evaluate);
+#endif
+#endif
+
+#if _CACHE_TOP_SCORE_
+                    score = m_tracker.get_top_sum() / g->size();
+#else
+                    score = top_score(g);
+#endif
+                } else {
+                    func_decl * fd = to_evaluate[new_const];              
+#if _REAL_RS_ || _REAL_PBFS_
+                    score = serious_score(g, fd, new_value);
+#else
+                    score = incremental_score(g, fd, new_value);    
+#endif
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        // main search loop
+        lbool search_old(goal_ref const & g) {        
+            lbool res = l_undef;
+            double score = 0.0, old_score = 0.0;
+            unsigned new_const = (unsigned)-1, new_bit = 0;        
+            mpz new_value;
+            move_type move;
+            
+            score = rescore(g);
+            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+                         tout << "Score distribution:"; 
+                         for (unsigned i = 0; i < g->size(); i++)
+                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                         tout << " TOP: " << score << std::endl; ); 
+        
+            unsigned plateau_cnt = 0;
+
+            // Andreas: Why do we only allow so few plateaus?
+#if _RESTARTS_
+            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
+            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
+#else
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
+#endif
+                do {
+                    checkpoint();
+
+#if _WEIGHT_DIST_ == 4
+                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+            
+#if _TYPE_RSTEP_
+                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+                    {
+#if _TYPE_RSTEP_ == 1
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _TYPE_RSTEP_ == 2
+                        mk_random_move(g);
+#endif
+                        score = top_score(g);
+
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                            } else
+                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                        }
+                    }
+#endif
+                    old_score = score;
+                    new_const = (unsigned)-1;
+                        
+                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+                    if (!to_evaluate.size())
+                    {
+                        res = l_true;
+                        goto bailout;
+                    }
+                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
+                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
+                                                tout << to_evaluate[i]->get_name() << std::endl; );
+
+#if _VNS_
+                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#else
+                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+#endif
+                    if (new_const == static_cast<unsigned>(-1)) {
+                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
+                                        for (unsigned i = 0; i < g->size(); i++) {
+                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                                        });
+
+                        TRACE("sls_max", m_tracker.show_model(tout);
+                                        tout << "Scores: " << std::endl;
+                                        for (unsigned i = 0; i < g->size(); i++)
+                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
+                                            m_tracker.get_score(g->form(i)) << std::endl; );
+                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
+                        score = old_score;
+                    }
+                    else {
+                        // Andreas: Why does randomizing not count as a move? (Now it does.)
+                        m_stats.m_moves++;
+                        func_decl * fd = to_evaluate[new_const];
+
+                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
+                                        switch (move) {
+                                        case MV_FLIP:  
+                                            tout << "Flip";
+                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
+                                            break;
+                                        case MV_INC: 
+                                            tout << "+1";
+                                            break;
+                                        case MV_DEC: 
+                                            tout << "-1";
+                                            break;
+                                        case MV_INV: 
+                                            tout << "NEG";
+                                            break;
+                                        };                                        
+                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
+
+                        switch (move) {
+                        case MV_FLIP: m_stats.m_flips++; break;
+                        case MV_INC: m_stats.m_incs++; break;
+                        case MV_DEC: m_stats.m_decs++; break;
+                        case MV_INV: m_stats.m_invs++; break;
+                        case MV_UMIN: m_stats.m_umins++; break;
+                        case MV_MUL2: m_stats.m_mul2s++; break;
+                        case MV_MUL3: m_stats.m_mul3s++; break;
+                        case MV_DIV2: m_stats.m_div2s++; break;
+                        }
+                    
+#if _REAL_RS_ || _REAL_PBFS_
+                        score = serious_score(g, fd, new_value);
+#else
+                        score = incremental_score(g, fd, new_value);    
+#endif
+
+                        TRACE("sls", tout << "Score distribution:"; 
+                                        for (unsigned i = 0; i < g->size(); i++)
+                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                                        tout << " TOP: " << score << std::endl; );                        
+                    }
+
+                    if (score >= 0.99999) {
+//                    if (score >= 1.0) {
+                        // score could theoretically be imprecise.
+                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
+                        bool all_true = true;
+                        for (unsigned i = 0; i < g->size() && all_true; i++)
+                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                all_true=false;
+                        if (all_true) {
+                            res = l_true; // sat
+                            goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
+                    /*
+                    if (m_stats.m_moves % 100 == 0)
+                    {
+                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
+                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+                    }*/
+                }
+                while (score > old_score && res == l_undef);                
+                
+                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
+                if (score != old_score) {
+                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
+                    plateau_cnt = 0;
+                } else {
+                    m_stats.m_moves++;
+                    plateau_cnt++;
+                    //report_tactic_progress("Plateau.", plateau_cnt);
+                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
+                    //if (plateau_cnt < m_plateau_limit) {
+                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
+#if _INTENSIFICATION_
+                        handle_plateau(g, score);
+                        //handle_plateau(g);
+#else
+                        m_evaluator.randomize_local(g, m_stats.m_moves);
+#endif
+                        //mk_random_move(g);
+                        score = top_score(g);
+
+                        if (score >= 1.0) {
+                            bool all_true = true;
+                            for (unsigned i = 0; i < g->size() && all_true; i++)
+                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                                    all_true=false;
+                            if (all_true) {
+                                res = l_true; // sat
+                                goto bailout;
+                        } else
+                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
+                    }
+                }
+            }
+
+            bailout:
+            m_mpz_manager.del(new_value);
+
+            return res;
+        }    
+
+        void operator()(goal_ref const & g, model_converter_ref & mc) {
+            if (g->inconsistent()) {
+                mc = 0;
+                return;
+            }
+
+            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
+            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
+            verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl;
+            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
+            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
+            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
+            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
+            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
+            verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl;
+            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
+            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
+            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
+            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
+            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
+            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
+            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
+            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
+            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
+            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
+            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+            verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
+            verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
+            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
+            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
+            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
+            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
+            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
+            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
+            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
+            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
+            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
+            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
+            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
+            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
+            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
+            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+            
+#if _WEIGHT_DIST_ == 4
+            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+            m_tracker.initialize(g);
+            lbool res = l_undef;
+        
+            m_restart_limit = _RESTART_LIMIT_;
+
+            do {
+                checkpoint();
+
+                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+                res = search(g);
+
+                if (res == l_undef)
+                {
+#if _RESTART_INIT_
+                    m_tracker.randomize(g);
+#else
+                    m_tracker.reset(g);
+#endif
+                }
+            }
+            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+        
+            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+
+            if (res == l_true) {    
+                report_tactic_progress("Number of flips:", m_stats.m_moves);
+                for (unsigned i = 0; i < g->size(); i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                    {
+                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                        NOT_IMPLEMENTED_YET(); 
+                    }
+
+                if (m_produce_models) {
+                    model_ref mdl = m_tracker.get_model();
+                    mc = model2model_converter(mdl.get());
+                    TRACE("sls_model", mc->display(tout); );
+                }
+                g->reset();
+            }
+            else
+                mc = 0;
+        }
+    };
+    
     ast_manager    & m;
     params_ref       m_params;
-    sls_engine     * m_engine;
+    imp            * m_imp;
+    stats            m_stats;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_engine = alloc(sls_engine, m, p);
+        m_imp = alloc(imp, m, p, m_stats);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -48,16 +1395,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_engine);
+        dealloc(m_imp);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_engine->updt_params(p);
+        m_imp->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        sls_params::collect_param_descrs(r);
+        imp::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -65,13 +1412,14 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());        
+        SASSERT(g->is_well_sorted());
+        m_imp->m_produce_models = g->models_enabled();        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_engine->operator()(g, mc);
+        m_imp->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -80,41 +1428,40 @@ public:
     }
 
     virtual void cleanup() {        
-        sls_engine * d = m_engine;
+        imp * d = m_imp;
         #pragma omp critical (tactic_cancel)
         {
-            d = m_engine;
+            d = m_imp;
         }
         dealloc(d);
-        d = alloc(sls_engine, m, m_params);
+        d = alloc(imp, m, m_params, m_stats);
         #pragma omp critical (tactic_cancel) 
         {
-            m_engine = d;
+            m_imp = d;
         }
     }
     
     virtual void collect_statistics(statistics & st) const {
-        sls_engine::stats const & stats = m_engine->get_stats();
-        double seconds = stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", stats.m_restarts);
-        st.update("sls full evals", stats.m_full_evals);
-        st.update("sls incr evals", stats.m_incr_evals);
-        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
-        st.update("sls FLIP moves", stats.m_flips);
-        st.update("sls INC moves", stats.m_incs);
-        st.update("sls DEC moves", stats.m_decs);
-        st.update("sls INV moves", stats.m_invs);
-        st.update("sls moves", stats.m_moves);
-        st.update("sls moves/sec", stats.m_moves / seconds);
+        double seconds = m_stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", m_stats.m_restarts);
+        st.update("sls full evals", m_stats.m_full_evals);
+        st.update("sls incr evals", m_stats.m_incr_evals);
+        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
+        st.update("sls FLIP moves", m_stats.m_flips);    
+        st.update("sls INC moves", m_stats.m_incs);
+        st.update("sls DEC moves", m_stats.m_decs);
+        st.update("sls INV moves", m_stats.m_invs);
+        st.update("sls moves", m_stats.m_moves);
+        st.update("sls moves/sec", m_stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_engine->reset_statistics();
+        m_stats.reset();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_engine)
-            m_engine->set_cancel(f);
+        if (m_imp)
+            m_imp->set_cancel(f);
     }
 };
 
@@ -163,7 +1510,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                         // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
                         //mk_ctx_simplify_tactic(m, ctx_p),
                         // Andreas: This one at least eliminates top level duplicates ...
-                        mk_simplify_tactic(m),
+                        //mk_simplify_tactic(m),
                         // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 3675265ee..1c33d42a7 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -276,6 +276,20 @@ public:
     }
 #endif
 
+    void uct_forget(goal_ref const & g) {
+        expr * e;
+        unsigned touched_old, touched_new;
+
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            e = g->form(i);
+            touched_old = m_scores.find(e).touched;
+            touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
+            m_scores.find(e).touched = touched_new;
+            m_touched += touched_new - touched_old;
+        }
+    }
+
     void initialize(app * n) {
         // Build score table
         if (!m_scores.contains(n)) {
@@ -1195,6 +1209,8 @@ public:
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); 
 #elif _UCT_ == 2
                 double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#elif _UCT_ == 3
+                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
                 if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
@@ -1202,7 +1218,7 @@ public:
             if (pos == static_cast<unsigned>(-1))
                 return m_temp_constants;
 
-#if _UCT_ == 1
+#if _UCT_ == 1 || _UCT_ == 3
             m_scores.find(g->form(pos)).touched++;
             m_touched++;
 #elif _UCT_ == 2
@@ -1343,6 +1359,8 @@ public:
                 double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
+#elif _UCT_ == 3
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
             if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
@@ -1350,7 +1368,7 @@ public:
         if (pos == static_cast<unsigned>(-1))
             return 0;
 
-#if _UCT_ == 1
+#if _UCT_ == 1 || _UCT_ == 3
         m_scores.find(g->form(pos)).touched++;
         m_touched++;
 #elif _UCT_ == 2

From 1f326d9e72157ec15d617ac804533809f8803573 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 26 Mar 2014 17:26:06 +0000
Subject: [PATCH 074/108] removed dependency of bvsls on goal_refs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp  | 219 +++++++++++++++++++--------------
 src/tactic/sls/sls_engine.h    |  58 ++++-----
 src/tactic/sls/sls_evaluator.h |   4 +-
 src/tactic/sls/sls_tracker.h   |  84 ++++++-------
 4 files changed, 195 insertions(+), 170 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 92471aad8..9fa2cc263 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -74,15 +74,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
+bool sls_engine::full_eval(model & mdl) {
     bool res = true;
 
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(g->form(i), o, true))
+        if (!mdl.eval(m_assertions[i], o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -93,7 +93,7 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     return res;
 }
 
-double sls_engine::top_score(goal_ref const & g) {
+double sls_engine::top_score() {
 #if 0
     double min = m_tracker.get_score(g->form(0));
     unsigned sz = g->size();
@@ -108,15 +108,15 @@ double sls_engine::top_score(goal_ref const & g) {
     return min;
 #else
     double top_sum = 0.0;
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = g->form(i);
+        expr * e = m_assertions[i];
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(g->form(i));
+        tout << " " << m_tracker.get_score(m_assertions[i]);
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
 #if _CACHE_TOP_SCORE_
@@ -127,40 +127,40 @@ double sls_engine::top_score(goal_ref const & g) {
 #endif
 }
 
-double sls_engine::rescore(goal_ref const & g) {
+double sls_engine::rescore() {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score(g);
+    return top_score();
 }
 
-double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
+    return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-    return top_score(g);
+    return top_score();
 #endif
 }
 
-double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
+    return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-    return top_score(g);
+    return top_score();
 #endif
 }
 
-double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
 #if _EARLY_PRUNE_
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-        return (m_tracker.get_top_sum() / g->size());
+        return (m_tracker.get_top_sum() / m_assertions.size());
 #else
-        return top_score(g);
+        return top_score();
 #endif
     else
         return 0.0;
@@ -170,8 +170,13 @@ double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, c
 }
 
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if(
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
@@ -179,9 +184,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 #endif
 
 #if _EARLY_PRUNE_
-    double r = incremental_score_prune(g, fd, temp);
+    double r = incremental_score_prune(fd, temp);
 #else
-    double r = incremental_score(g, fd, temp);
+    double r = incremental_score(fd, temp);
 #endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
@@ -202,8 +207,15 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 }
 
 // same as what_if, but only applied to the score of a specific atom, not the total score
-bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                    double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if_local(
+    expr * e, 
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) 
+{
     m_evaluator.update(fd, temp);
     double r = m_tracker.get_score(e);
     if (r >= best_score) {
@@ -344,13 +356,19 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     m_mpz_manager.del(new_value);
 }
 
-void sls_engine::mk_random_move(goal_ref const & g) {
-    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
+void sls_engine::mk_random_move() {
+    mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves));
 }
 
 // will use VNS to ignore some possible moves and increase the flips per second
-double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move_vns(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
     unsigned bv_sz, max_bv_sz = 0;
     double new_score = score;
@@ -366,31 +384,31 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
             // try to flip lsb
             mk_flip(srt, old_value, 0, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = 0;
                 move = MV_FLIP;
             }
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         SASSERT(check == score);
     }
 
@@ -412,13 +430,13 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
                 {
                     mk_flip(srt, old_value, j, temp);
 
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                    if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                         new_bit = j;
                         move = MV_FLIP;
                     }
                 }
                 // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
+                double check = incremental_score(fd, old_value);
                 SASSERT(check == score);
             }
     m_mpz_manager.del(old_value);
@@ -427,8 +445,14 @@ double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl>
 }
 
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
     mpz temp2;
@@ -451,7 +475,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
@@ -462,19 +486,19 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
 #if _USE_UNARY_MINUS_
@@ -504,7 +528,7 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         // Andreas: does not hold anymore now that we use top level score caching
         //SASSERT(check == score);
     }
@@ -572,15 +596,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_eva
 }
 
 // first try of intensification ... does not seem to be efficient
-bool sls_engine::handle_plateau(goal_ref const & g)
+bool sls_engine::handle_plateau()
 {
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
 #if _BFS_
     unsigned pos = m_stats.m_moves % sz;
 #else
     unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
+    expr * e = m_tracker.get_unsat_assertion(sz, pos);
     if (!e)
         return 0;
 
@@ -634,10 +658,15 @@ bool sls_engine::handle_plateau(goal_ref const & g)
 }
 
 // what_if version needed in the context of 2nd intensification try, combining local and global score
-bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                double & best_score, mpz & best_value, unsigned i) {
-
-    double global_score = incremental_score(g, fd, temp);
+bool sls_engine::what_if(
+    expr * e, 
+    func_decl * fd, 
+    const mpz & temp,
+    double & best_score, 
+    mpz & best_value, 
+    unsigned i) 
+{
+    double global_score = incremental_score(fd, temp);
     double local_score = m_tracker.get_score(e);
     double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
@@ -651,7 +680,7 @@ bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz
 }
 
 // find_best_move version needed in the context of 2nd intensification try
-double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
+double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i)
 {
     mpz old_value, temp;
     double best_score = 0;
@@ -662,7 +691,7 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl
 
     for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
         mk_flip(srt, old_value, j, temp);
-        what_if(g, e, fd, temp, best_score, best_value, i);
+        what_if(e, fd, temp, best_score, best_value, i);
     }
 
     m_mpz_manager.del(old_value);
@@ -672,15 +701,15 @@ double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl
 }
 
 // second try to use intensification ... also not very effective
-bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
+bool sls_engine::handle_plateau(double old_score)
 {
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
 #if _BFS_
     unsigned new_const = m_stats.m_moves % sz;
 #else
     unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
+    expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const);
     if (!e)
         return 0;
 
@@ -697,12 +726,12 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 
     for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
     {
-        new_score = find_best_move_local(g, q, fd, new_value, i);
+        new_score = find_best_move_local(q, fd, new_value, i);
 
         m_stats.m_moves++;
         m_stats.m_flips++;
 
-        global_score = incremental_score(g, fd, new_value);
+        global_score = incremental_score(fd, new_value);
         local_score = m_tracker.get_score(q);
 
         SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
@@ -715,7 +744,7 @@ bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 }
 
 // main search loop
-lbool sls_engine::search(goal_ref const & g) {
+lbool sls_engine::search() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
@@ -723,8 +752,8 @@ lbool sls_engine::search(goal_ref const & g) {
     move_type move;
     unsigned plateau_cnt = 0;
 
-    score = rescore(g);
-    unsigned sz = g->size();
+    score = rescore();
+    unsigned sz = m_assertions.size();
 #if _PERC_STICKY_
     expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
@@ -750,7 +779,7 @@ lbool sls_engine::search(goal_ref const & g) {
         if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
             e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #else
-        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
+        expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves);
 #endif
         if (!e)
         {
@@ -793,7 +822,7 @@ lbool sls_engine::search(goal_ref const & g) {
 #if _VNS_
         score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
 
         if (new_const == static_cast<unsigned>(-1)) {
@@ -811,14 +840,14 @@ lbool sls_engine::search(goal_ref const & g) {
             else
 #endif
 #if _REPICK_
-                m_evaluator.randomize_local(g, m_stats.m_moves);
+                m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
 #else
                 m_evaluator.randomize_local(to_evaluate);
 #endif
 #endif
 
 #if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / g->size();
+            score = m_tracker.get_top_sum() / m_assertions.size();
 #else
             score = top_score(g);
 #endif
@@ -828,7 +857,7 @@ lbool sls_engine::search(goal_ref const & g) {
 #if _REAL_RS_ || _REAL_PBFS_
             score = serious_score(g, fd, new_value);
 #else
-            score = incremental_score(g, fd, new_value);
+            score = incremental_score(fd, new_value);
 #endif
         }
     }
@@ -840,18 +869,18 @@ bailout:
 }
 
 // main search loop
-lbool sls_engine::search_old(goal_ref const & g) {
+lbool sls_engine::search_old() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
     mpz new_value;
     move_type move;
 
-    score = rescore(g);
+    score = rescore();
     TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
     tout << "Score distribution:";
-    for (unsigned i = 0; i < g->size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    for (unsigned i = 0; i < m_assertions.size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
     tout << " TOP: " << score << std::endl;);
 
     unsigned plateau_cnt = 0;
@@ -897,7 +926,7 @@ lbool sls_engine::search_old(goal_ref const & g) {
             old_score = score;
             new_const = (unsigned)-1;
 
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves);
             if (!to_evaluate.size())
             {
                 res = l_true;
@@ -908,22 +937,22 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 tout << to_evaluate[i]->get_name() << std::endl;);
 
 #if _VNS_
-            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
             if (new_const == static_cast<unsigned>(-1)) {
                 TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++) {
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
+                for (unsigned i = 0; i < m_assertions.size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
+                        tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl;
                 });
 
                 TRACE("sls_max", m_tracker.show_model(tout);
                 tout << "Scores: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
-                    m_tracker.get_score(g->form(i)) << std::endl;);
+                for (unsigned i = 0; i < m_assertions.size(); i++)
+                    tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " <<
+                    m_tracker.get_score(m_assertions[i]) << std::endl;);
                 // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                 score = old_score;
             }
@@ -962,14 +991,14 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 }
 
 #if _REAL_RS_ || _REAL_PBFS_
-                score = serious_score(g, fd, new_value);
+                score = serious_score(fd, new_value);
 #else
-                score = incremental_score(g, fd, new_value);
+                score = incremental_score(fd, new_value);
 #endif
 
                 TRACE("sls", tout << "Score distribution:";
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+                for (unsigned i = 0; i < m_assertions.size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
                 tout << " TOP: " << score << std::endl;);
             }
 
@@ -978,8 +1007,8 @@ lbool sls_engine::search_old(goal_ref const & g) {
                 // score could theoretically be imprecise.
                 // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                 bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1010,17 +1039,17 @@ lbool sls_engine::search_old(goal_ref const & g) {
             TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
 #if _INTENSIFICATION_
             handle_plateau(g, score);
-            //handle_plateau(g);
+            //handle_plateau();
 #else
-            m_evaluator.randomize_local(g, m_stats.m_moves);
+            m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
 #endif
-            //mk_random_move(g);
-            score = top_score(g);
+            //mk_random_move();
+            score = top_score();
 
             if (score >= 1.0) {
                 bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1046,6 +1075,10 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
+    for (unsigned i = 0; i < g->size(); i++)
+        assert_expr(g->form(i));
+    
+
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
     verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
@@ -1089,7 +1122,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 #if _WEIGHT_TOGGLE_
     m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
 #endif
-    m_tracker.initialize(g);
+    m_tracker.initialize(m_assertions);
     lbool res = l_undef;
 
     m_restart_limit = _RESTART_LIMIT_;
@@ -1098,14 +1131,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         checkpoint();
 
         report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search(g);
+        res = search();
 
         if (res == l_undef)
         {
 #if _RESTART_INIT_
-            m_tracker.randomize(g);
+            m_tracker.randomize();
 #else
-            m_tracker.reset(g);
+            m_tracker.reset(m_assertions);
 #endif
         }
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 878354c6d..8458817b6 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -71,6 +71,7 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
+    ptr_vector<expr> m_assertions;
 
     unsigned		m_restart_limit;
     unsigned        m_max_restarts;
@@ -92,11 +93,12 @@ public:
 
     void updt_params(params_ref const & _p);
 
+    void assert_expr(expr * e) { m_assertions.push_back(e); }
+
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(goal_ref const & g, model & mdl);
-    
+    bool full_eval(model & mdl);
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
     void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
@@ -104,54 +106,44 @@ public:
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
-    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    
-    
-    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                 double & best_score, mpz & best_value, unsigned i);
-    
-    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
-    
-
-    lbool search(goal_ref const & g);    
+    lbool search(void);    
 
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
-    lbool search_old(goal_ref const & g);
+    lbool search_old(void);
     double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
-
+    bool what_if(expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
     bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                        double & best_score, unsigned & best_const, mpz & best_value);
 
-    double top_score(goal_ref const & g);
-    double rescore(goal_ref const & g);
-    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
-    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double top_score();
+    double rescore();
+    double serious_score(func_decl * fd, const mpz & new_value);
+    double incremental_score(func_decl * fd, const mpz & new_value);
 
 #if _EARLY_PRUNE_
-    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score_prune(func_decl * fd, const mpz & new_value);
 #endif
-
-    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-
+    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
+    double find_best_move_vns(ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
-    void mk_random_move(goal_ref const & g);
+    void mk_random_move();
 
-    bool handle_plateau(goal_ref const & g);
-    bool handle_plateau(goal_ref const & g, double old_score);
+    bool handle_plateau(void);
+    bool handle_plateau(double old_score);
 
     inline unsigned check_restart(unsigned curr_value);
 };
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 9daf93c32..7638ba5f4 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -922,8 +922,8 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-     void randomize_local(goal_ref const & g, unsigned int flip) {
-        randomize_local(m_tracker.get_unsat_constants(g, flip));
+    void randomize_local(ptr_vector<expr> const & as, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(as, flip));
     } 
 };
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 1c33d42a7..c49257692 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,7 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"goal.h"
+#include"bv_decl_plugin.h"
 #include"model.h"
 
 #include"sls_compilation_settings.h"
@@ -365,12 +365,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(goal_ref const & g) {
+    void calculate_expr_distances(ptr_vector<expr> const & as) {
         // precondition: m_scores is set up.
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(g->form(i)));
+            stack.push_back(to_app(as[i]));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -418,12 +418,12 @@ public:
         quick_for_each_expr(ffd_proc, visited, e);
     }
 
-    void initialize(goal_ref const & g) {
+    void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
             else
@@ -438,7 +438,7 @@ public:
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
             initialize_recursive(e);
@@ -450,7 +450,7 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(g);
+        calculate_expr_distances(as);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
@@ -465,11 +465,11 @@ public:
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-            setup_occs(g->form(i));
+            setup_occs(as[i]);
 #endif
 
 #if _UCT_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
 #endif
     }
 
@@ -606,7 +606,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(goal_ref const & g) {
+    void randomize(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -620,13 +620,13 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
+        for (unsigned i = 0; i < as.size(); i++)
+            m_scores.find(as[i]).touched = 1;
 #endif
     }              
 
-    void reset(goal_ref const & g) {
+    void reset(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -636,9 +636,9 @@ public:
         }
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
+        m_touched = _UCT_INIT_ ? as.size() : 1;
+        for (unsigned i = 0; i < as.size(); i++)
+            m_scores.find(as[i]).touched = 1;
 #endif
     }              
 
@@ -1029,13 +1029,13 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as, unsigned sz) {
         if (sz == 1)
             return get_constants();
         m_temp_constants.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * q = g->form(i);
+            expr * q = as[i];
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -1049,22 +1049,22 @@ public:
         return m_temp_constants;
     }
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
+    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
             for (unsigned i = pos; i < sz; i++) {
-                expr * q = g->form(i);
+                expr * q = as[i];
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
+                expr * q = as[i];
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             return 0;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-            expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(as, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
             if (!q)
                 return m_temp_constants;
@@ -1141,19 +1141,19 @@ public:
             return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-        expr * q = get_unsat_assertion(g, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(as, sz, pos);
         if (!q)
             return m_temp_constants;
 
         return go_deeper(q);
     }
 
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
+    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as, unsigned int flip) {
+        unsigned sz = as.size();
 
         if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            if (m_mpz_manager.eq(get_value(as[0]), m_one))
                 return m_temp_constants;
             else
                 return get_constants();
@@ -1201,7 +1201,7 @@ public:
 #else
             double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1219,12 +1219,12 @@ public:
                 return m_temp_constants;
 
 #if _UCT_ == 1 || _UCT_ == 3
-            m_scores.find(g->form(pos)).touched++;
+            m_scores.find(as[pos]).touched++;
             m_touched++;
 #elif _UCT_ == 2
-            m_scores.find(g->form(pos)).touched = flip; 
+            m_scores.find(as[pos]).touched = flip; 
 #endif
-            expr * e = g->form(pos);
+            expr * e = as[pos];
 //            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
@@ -1303,11 +1303,11 @@ public:
     }
     
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
+    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned int flip) {
+        unsigned sz = as.size();
 
         if (sz == 1)
-            return g->form(0);
+            return as[0];
 
         m_temp_constants.reset();
 #if _FOCUS_ == 1
@@ -1351,7 +1351,7 @@ public:
 #else
         double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1369,13 +1369,13 @@ public:
             return 0;
 
 #if _UCT_ == 1 || _UCT_ == 3
-        m_scores.find(g->form(pos)).touched++;
+        m_scores.find(as[pos]).touched++;
         m_touched++;
 #elif _UCT_ == 2
         m_scores.find(g->form(pos)).touched = flip; 
 #endif
 //        return m_list_false[pos];
-        return g->form(pos);
+        return as[pos];
 
 #elif _BFS_ == 3
         unsigned int pos = -1;
@@ -1429,7 +1429,7 @@ public:
         unsigned int pos = get_random_uint(16) % sz;
         return get_unsat_assertion(g, sz, pos);
 #endif
-        return g->form(pos);
+        return as[pos];
 #elif _FOCUS_ == 2
 #if _BFS_
         unsigned int pos = flip % sz;

From 1834bb59504733a159ae6f1832eae01d5ec0fc02 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 27 Mar 2014 13:34:21 +0000
Subject: [PATCH 075/108] disabled old code

---
 src/tactic/sls/sls_engine.cpp | 4 +++-
 src/tactic/sls/sls_engine.h   | 3 +--
 2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 9fa2cc263..cc06e4f78 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -868,6 +868,7 @@ bailout:
     return res;
 }
 
+#if 0 // Old code.
 // main search loop
 lbool sls_engine::search_old() {
     lbool res = l_undef;
@@ -1060,6 +1061,7 @@ lbool sls_engine::search_old() {
             }
         }
     }
+#endif
 
 bailout:
     m_mpz_manager.del(new_value);
@@ -1190,4 +1192,4 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         return 0;
     }
     return 1;
-}
\ No newline at end of file
+}
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8458817b6..5d4c9a0fc 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -114,7 +114,6 @@ public:
 
 protected:
     void checkpoint();
-    lbool search_old(void);
     double get_restart_armin(unsigned cnt_restarts);    
 
     bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
@@ -148,4 +147,4 @@ protected:
     inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
\ No newline at end of file
+#endif

From e9797c392272e90dd7b9ffb43e537098c9f354dd Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 27 Mar 2014 13:37:04 +0000
Subject: [PATCH 076/108] bugfix

---
 src/tactic/sls/sls_engine.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index cc06e4f78..10aaf6601 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1061,13 +1061,13 @@ lbool sls_engine::search_old() {
             }
         }
     }
-#endif
 
 bailout:
     m_mpz_manager.del(new_value);
 
     return res;
 }
+#endif
 
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {

From 71fdb597475d5178ac3a6ec8309cf2cc6b659bce Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:27:06 +0000
Subject: [PATCH 077/108] removed dependency of bvsls on goal_refs

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index c49257692..cf1ad9ea3 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -276,13 +276,13 @@ public:
     }
 #endif
 
-    void uct_forget(goal_ref const & g) {
+    void uct_forget(ptr_vector<expr> & as) {
         expr * e;
         unsigned touched_old, touched_new;
 
-        for (unsigned i = 0; i < g->size(); i++)
+        for (unsigned i = 0; i < as.size(); i++)
         {
-            e = g->form(i);
+            e = as[i];
             touched_old = m_scores.find(e).touched;
             touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
             m_scores.find(e).touched = touched_new;

From b76ffddf49c0d42472573c41d20c072b503d3e78 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:28:40 +0000
Subject: [PATCH 078/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index cf1ad9ea3..fac080ee7 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,6 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
+#include"for_each_expr.h"
 #include"bv_decl_plugin.h"
 #include"model.h"
 

From 1b98e6002b7a70ee51f00227ecdecb663a2fe113 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 12:30:15 +0000
Subject: [PATCH 079/108] compilation fixes

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.h  | 1 +
 src/tactic/sls/sls_tracker.h | 1 +
 2 files changed, 2 insertions(+)

diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 5d4c9a0fc..96041d09e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,6 +22,7 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
+#include"goal.h"
 
 #include"sls_compilation_settings.h"
 #include"sls_tracker.h"
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index fac080ee7..537492213 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -21,6 +21,7 @@ Notes:
 #define _SLS_TRACKER_H_
 
 #include"for_each_expr.h"
+#include"ast_smt2_pp.h"
 #include"bv_decl_plugin.h"
 #include"model.h"
 

From ad412d4f08f63e61778f940fef7afdb0f54c7f51 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 14:58:59 +0000
Subject: [PATCH 080/108] bvsls refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 21 ++++++++++++---------
 src/tactic/sls/sls_engine.h   |  2 ++
 2 files changed, 14 insertions(+), 9 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 10aaf6601..e7ee2abbd 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1069,6 +1069,16 @@ bailout:
 }
 #endif
 
+void sls_engine::init_tracker() {
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(m_assertions);
+}
+
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {
         mc = 0;
@@ -1078,8 +1088,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     m_produce_models = g->models_enabled();
 
     for (unsigned i = 0; i < g->size(); i++)
-        assert_expr(g->form(i));
-    
+        assert_expr(g->form(i));    
 
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
@@ -1118,13 +1127,7 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
     verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-#if _WEIGHT_DIST_ == 4
-    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-    m_tracker.initialize(m_assertions);
+    init_tracker();
     lbool res = l_undef;
 
     m_restart_limit = _RESTART_LIMIT_;
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 96041d09e..c56d6ec40 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -109,6 +109,8 @@ public:
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
     void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
+    void init_tracker(void);
+
     lbool search(void);    
 
     void operator()(goal_ref const & g, model_converter_ref & mc);

From e382742a29f06e818bf361e2829abe18d118d710 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 15:26:52 +0000
Subject: [PATCH 081/108] bvsls refactoring

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 44 +++++++++++++++++++----------------
 src/tactic/sls/sls_engine.h   |  1 +
 2 files changed, 25 insertions(+), 20 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index e7ee2abbd..2b359608a 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1125,8 +1125,31 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
     verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;    
 
+    lbool res = operator()();
+
+    if (res == l_true) {
+        report_tactic_progress("Number of flips:", m_stats.m_moves);
+        for (unsigned i = 0; i < g->size(); i++)
+            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+            {
+                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
+                NOT_IMPLEMENTED_YET();
+            }
+
+        if (m_produce_models) {
+            model_ref mdl = m_tracker.get_model();
+            mc = model2model_converter(mdl.get());
+            TRACE("sls_model", mc->display(tout););
+        }
+        g->reset();
+    }
+    else
+        mc = 0;
+}
+
+lbool sls_engine::operator()() {
     init_tracker();
     lbool res = l_undef;
 
@@ -1149,25 +1172,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
 
     verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-    if (res == l_true) {
-        report_tactic_progress("Number of flips:", m_stats.m_moves);
-        for (unsigned i = 0; i < g->size(); i++)
-            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-            {
-                verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                NOT_IMPLEMENTED_YET();
-            }
-
-        if (m_produce_models) {
-            model_ref mdl = m_tracker.get_model();
-            mc = model2model_converter(mdl.get());
-            TRACE("sls_model", mc->display(tout););
-        }
-        g->reset();
-    }
-    else
-        mc = 0;
 }
 
 unsigned sls_engine::check_restart(unsigned curr_value)
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index c56d6ec40..c6e3af155 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -113,6 +113,7 @@ public:
 
     lbool search(void);    
 
+    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:

From a48bb976e9ae28e0eb60600ef8d9e43cb1c906e7 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 28 Mar 2014 15:28:02 +0000
Subject: [PATCH 082/108] bvsls bugfix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 2b359608a..dc4451bb5 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -1172,6 +1172,8 @@ lbool sls_engine::operator()() {
     } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
 
     verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+    
+    return res;
 }
 
 unsigned sls_engine::check_restart(unsigned curr_value)

From c56e55b2305d0c26023a588b5c6d5dba1e79da87 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Sun, 20 Apr 2014 16:38:49 +0100
Subject: [PATCH 083/108] Current version before integration ...

---
 src/tactic/sls/sls_compilation_settings.h |  40 +-
 src/tactic/sls/sls_engine.cpp             | 586 +++++++++++++++-------
 src/tactic/sls/sls_engine.h               |  73 +--
 src/tactic/sls/sls_evaluator.h            | 152 +++++-
 src/tactic/sls/sls_tactic.cpp             |   4 +-
 src/tactic/sls/sls_tracker.h              | 472 ++++++++++++++---
 6 files changed, 1040 insertions(+), 287 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 8e52596e0..d2b899dd8 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -36,17 +36,21 @@ Notes:
 // do we use dirty unit propagation to get rid of nested top level assertions?
 #define _DIRTY_UP_ 0
 
+// shall we use additive weighting scheme?
+#define _PAWS_ 5
+#define _PAWS_INIT_ 40
+
 // do we use restarts?
 // 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
+#define _RESTARTS_ 1
 // limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
+#define _RESTART_LIMIT_ 100
 // 0 = initialize with all zero, 1 initialize with random value
 #define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid
+// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
 #define _RESTART_SCHEME_ 1
 // base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 3.0
+#define _RESTART_CONST_ARMIN_ 2.0
 
 // timelimit
 #define _TIMELIMIT_ 3600
@@ -61,6 +65,21 @@ Notes:
 // 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
 #define _VNS_ 0
 
+// shall we check 2-bit flips in plateaus using Monte Carlo?
+#define _VNS_MC_ 0
+
+// how many 2-bit flips shall we try per bit?
+#define _VNS_MC_TRIES_ 1
+
+// shall we check another assertion if no improving step was found in the first one?
+#define _VNS_REPICK_ 0
+
+// what is the probability of doing so (percentage)?
+#define _VNS_PERC_ 100
+
+// do a decreasing move with percentage ...
+#define _INSIST_PERC_ 0
+
 // do we reduce the score of unsatisfied literals?
 // 0 = no
 // 1 = yes, by multiplying it with some factor
@@ -70,7 +89,7 @@ Notes:
 #define _WEIGHT_DIST_ 1
 
 // the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.25
+#define _WEIGHT_DIST_FACTOR_ 0.5
 
 // shall we toggle the weight after each restart?
 #define _WEIGHT_TOGGLE_ 0
@@ -82,14 +101,15 @@ Notes:
 // what is the percentage of random moves in plateaus (instead of full randomization)?
 #define _PERC_PLATEAU_MOVES_ 0
 
-// shall we repick clause when randomizing in a plateau or use the current one?
+// shall we repick assertion when randomizing in a plateau or use the current one?
+// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one
 #define _REPICK_ 1
 
 // do we use some UCT-like scheme for assertion-selection? overrides _BFS_
 #define _UCT_ 1
 
 // how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 10.0
+#define _UCT_CONSTANT_ 20.0
 
 // is uct clause selection probabilistic similar to variable selection in sparrow?
 // 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
@@ -103,7 +123,11 @@ Notes:
 
 // how shall we initialize the _UCT_ total touched counter?
 // 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 1
+#define _UCT_INIT_ 0
+
+// do we gradually reduce the touched values of _UCT_?
+#define _UCT_FORGET_ 0
+#define _UCT_FORGET_FACTOR_ 0.9
 
 // shall we use addition/subtraction?
 #define _USE_ADDSUB_ 1
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index dc4451bb5..342e649af 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -74,15 +74,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(model & mdl) {
+bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     bool res = true;
 
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(m_assertions[i], o, true))
+        if (!mdl.eval(g->form(i), o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -93,7 +93,7 @@ bool sls_engine::full_eval(model & mdl) {
     return res;
 }
 
-double sls_engine::top_score() {
+double sls_engine::top_score(goal_ref const & g) {
 #if 0
     double min = m_tracker.get_score(g->form(0));
     unsigned sz = g->size();
@@ -108,15 +108,15 @@ double sls_engine::top_score() {
     return min;
 #else
     double top_sum = 0.0;
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = m_assertions[i];
+        expr * e = g->form(i);
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(m_assertions[i]);
+        tout << " " << m_tracker.get_score(g->form(i));
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
 #if _CACHE_TOP_SCORE_
@@ -127,40 +127,40 @@ double sls_engine::top_score() {
 #endif
 }
 
-double sls_engine::rescore() {
+double sls_engine::rescore(goal_ref const & g) {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score();
+    return top_score(g);
 }
 
-double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return (m_tracker.get_top_sum() / g->size());
 #else
-    return top_score();
+    return top_score(g);
 #endif
 }
 
-double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
 #if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return (m_tracker.get_top_sum() / g->size());
 #else
-    return top_score();
+    return top_score(g);
 #endif
 }
 
-double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
 #if _EARLY_PRUNE_
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
 #if _CACHE_TOP_SCORE_
-        return (m_tracker.get_top_sum() / m_assertions.size());
+        return (m_tracker.get_top_sum() / g->size());
 #else
-        return top_score();
+        return top_score(g);
 #endif
     else
         return 0.0;
@@ -169,14 +169,17 @@ double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value
 #endif
 }
 
+double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+    m_stats.m_incr_evals++;
+    if (m_evaluator.update_prune_new(fd, new_value))
+        return (m_tracker.get_top_sum() / g->size());
+    else
+        return 0.0;
+}
+
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(
-    func_decl * fd, 
-    const unsigned & fd_inx, 
-    const mpz & temp,
-    double & best_score, 
-    unsigned & best_const, 
-    mpz & best_value) {
+bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
@@ -184,9 +187,9 @@ bool sls_engine::what_if(
 #endif
 
 #if _EARLY_PRUNE_
-    double r = incremental_score_prune(fd, temp);
+    double r = incremental_score_prune(g, fd, temp);
 #else
-    double r = incremental_score(fd, temp);
+    double r = incremental_score(g, fd, temp);
 #endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
@@ -195,8 +198,33 @@ bool sls_engine::what_if(
     m_mpz_manager.del(old_value);
 #endif
 
-    //            if (r >= best_score) {
+    //if (r >= best_score) {
     if (r > best_score) {
+        m_tracker.reset_equal_scores();
+        best_score = r;
+        best_const = fd_inx;
+        m_mpz_manager.set(best_value, temp);
+        return true;
+    }
+    /*else if (r == best_score) {
+        if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0)
+        {
+            best_score = r;
+            best_const = fd_inx;
+            m_mpz_manager.set(best_value, temp);
+            return true;
+        }
+    }*/
+
+    return false;
+}
+
+bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                double & best_score, unsigned & best_const, mpz & best_value) {
+
+    double r = incremental_score_prune_new(g, fd, temp);
+
+    if (r >= best_score) {
         best_score = r;
         best_const = fd_inx;
         m_mpz_manager.set(best_value, temp);
@@ -207,15 +235,8 @@ bool sls_engine::what_if(
 }
 
 // same as what_if, but only applied to the score of a specific atom, not the total score
-bool sls_engine::what_if_local(
-    expr * e, 
-    func_decl * fd, 
-    const unsigned & fd_inx, 
-    const mpz & temp,
-    double & best_score, 
-    unsigned & best_const, 
-    mpz & best_value) 
-{
+bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                    double & best_score, unsigned & best_const, mpz & best_value) {
     m_evaluator.update(fd, temp);
     double r = m_tracker.get_score(e);
     if (r >= best_score) {
@@ -356,19 +377,13 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     m_mpz_manager.del(new_value);
 }
 
-void sls_engine::mk_random_move() {
-    mk_random_move(m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves));
+void sls_engine::mk_random_move(goal_ref const & g) {
+    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
 }
 
 // will use VNS to ignore some possible moves and increase the flips per second
-double sls_engine::find_best_move_vns(
-    ptr_vector<func_decl> & to_evaluate, 
-    double score,
-    unsigned & best_const, 
-    mpz & best_value, 
-    unsigned & new_bit, 
-    move_type & move) 
-{
+double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
     mpz old_value, temp;
     unsigned bv_sz, max_bv_sz = 0;
     double new_score = score;
@@ -384,31 +399,31 @@ double sls_engine::find_best_move_vns(
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(fd, i, temp, new_score, best_const, best_value))
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
             // try to flip lsb
             mk_flip(srt, old_value, 0, temp);
-            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = 0;
                 move = MV_FLIP;
             }
         }
 
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
+        double check = incremental_score(g, fd, old_value);
         SASSERT(check == score);
     }
 
@@ -430,13 +445,13 @@ double sls_engine::find_best_move_vns(
                 {
                     mk_flip(srt, old_value, j, temp);
 
-                    if (what_if(fd, i, temp, new_score, best_const, best_value)) {
+                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
                         new_bit = j;
                         move = MV_FLIP;
                     }
                 }
                 // reset to what it was before
-                double check = incremental_score(fd, old_value);
+                double check = incremental_score(g, fd, old_value);
                 SASSERT(check == score);
             }
     m_mpz_manager.del(old_value);
@@ -444,23 +459,99 @@ double sls_engine::find_best_move_vns(
     return new_score;
 }
 
+double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+    mpz old_value, temp;
+    unsigned bv_sz, max_bv_sz = 0;
+    double new_score = score;
+
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
+            // try inverting
+            mk_inv(bv_sz, old_value, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                move = MV_INV;
+
+            if (!m_mpz_manager.is_even(old_value)) {
+                // for odd values, try +1
+                mk_inc(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_INC;
+            }
+            else {
+                // for even values, try -1
+                mk_dec(bv_sz, old_value, temp);
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                    move = MV_DEC;
+            }
+
+            // try to flip lsb
+            mk_flip(srt, old_value, 0, temp);
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                new_bit = 0;
+                move = MV_FLIP;
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+        SASSERT(check == score);
+    }
+
+    for (unsigned j = 1; j < max_bv_sz; j++)
+    {
+        for (unsigned i = 0; i < to_evaluate.size(); i++) {
+            func_decl * fd = to_evaluate[i];
+            sort * srt = fd->get_range();
+            bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+            // What would happen if we flipped bit #j ?                
+            if (j < bv_sz)
+            {
+                mk_flip(srt, old_value, j, temp);
+
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+                    new_bit = j;
+                    move = MV_FLIP;
+                }
+            }
+            // reset to what it was before
+            double check = incremental_score(g, fd, old_value);
+            SASSERT(check == score);
+        }
+    }
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    return new_score;
+}
+
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(
-    ptr_vector<func_decl> & to_evaluate, 
-    double score,
-    unsigned & best_const, 
-    mpz & best_value, 
-    unsigned & new_bit, 
-    move_type & move) 
-{
+double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
     mpz old_value, temp;
 #if _USE_MUL3_ || _USE_UNARY_MINUS_
     mpz temp2;
 #endif
     unsigned bv_sz;
+#if _INSIST_PERC_
+    double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score;
+#else
     double new_score = score;
+#endif
 
-    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    m_tracker.reset_equal_scores();
+
+//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+//    for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) {
+//    for (unsigned i = to_evaluate.size(); i-- > 0; ) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -470,15 +561,28 @@ double sls_engine::find_best_move(
 #if _SKIP_BITS_
         for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
 #else
-        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+//        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+        for (unsigned j = 0; j < bv_sz; j++) {
+//        for (unsigned j = bv_sz; j-- > 0; ) {
 #endif
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
+            //if (m_tracker.get_random_uint(1))
+            //if ((move != MV_FLIP) || (new_bit > j))
+            //{
+            //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) {
+            //    new_bit = j;
+            //    move = MV_FLIP;
+            //}
+            //}
+            //else
+            //{
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
+            //}
         }
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -486,19 +590,22 @@ double sls_engine::find_best_move(
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                //if (m_tracker.get_random_uint(1))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                if (what_if(fd, i, temp, new_score, best_const, best_value))
+                //if (m_tracker.get_random_uint(1))
+                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            if (what_if(fd, i, temp, new_score, best_const, best_value))
+            //if (m_tracker.get_random_uint(1))
+            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
 
 #if _USE_UNARY_MINUS_
@@ -528,7 +635,7 @@ double sls_engine::find_best_move(
         }
 
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
+        double check = incremental_score(g, fd, old_value);
         // Andreas: does not hold anymore now that we use top level score caching
         //SASSERT(check == score);
     }
@@ -538,6 +645,50 @@ double sls_engine::find_best_move(
 #if _USE_MUL3_
     m_mpz_manager.del(temp2);
 #endif
+
+    if ((new_score == score) && 1)// (m_tracker.get_random_uint(1)))
+        best_const = -1;
+
+    return new_score;
+}
+
+// finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
+double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                        unsigned & best_const, mpz & best_value) {
+    mpz old_value, temp, temp2;
+    unsigned bv_sz;
+    double new_score = score;
+
+//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
+    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+        func_decl * fd = to_evaluate[i];
+        sort * srt = fd->get_range();
+        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
+        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
+
+        if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) {
+//            for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
+            for (unsigned j = 0; j < bv_sz; j++) {
+                mk_flip(srt, old_value, j, temp);
+                for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++)
+                {
+                    unsigned k = m_tracker.get_random_uint(16) % bv_sz;
+                    while (k == j)
+                        k = m_tracker.get_random_uint(16) % bv_sz;
+                    mk_flip(srt, temp, k, temp2);
+                    what_if(g, fd, i, temp2, new_score, best_const, best_value);
+                }
+            }
+        }
+
+        // reset to what it was before
+        double check = incremental_score(g, fd, old_value);
+    }
+
+    m_mpz_manager.del(old_value);
+    m_mpz_manager.del(temp);
+    m_mpz_manager.del(temp2);
+
     return new_score;
 }
 
@@ -596,15 +747,15 @@ double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_eva
 }
 
 // first try of intensification ... does not seem to be efficient
-bool sls_engine::handle_plateau()
+bool sls_engine::handle_plateau(goal_ref const & g)
 {
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
 #if _BFS_
     unsigned pos = m_stats.m_moves % sz;
 #else
     unsigned pos = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(sz, pos);
+    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
     if (!e)
         return 0;
 
@@ -658,15 +809,10 @@ bool sls_engine::handle_plateau()
 }
 
 // what_if version needed in the context of 2nd intensification try, combining local and global score
-bool sls_engine::what_if(
-    expr * e, 
-    func_decl * fd, 
-    const mpz & temp,
-    double & best_score, 
-    mpz & best_value, 
-    unsigned i) 
-{
-    double global_score = incremental_score(fd, temp);
+bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                double & best_score, mpz & best_value, unsigned i) {
+
+    double global_score = incremental_score(g, fd, temp);
     double local_score = m_tracker.get_score(e);
     double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
 
@@ -680,7 +826,7 @@ bool sls_engine::what_if(
 }
 
 // find_best_move version needed in the context of 2nd intensification try
-double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i)
+double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
 {
     mpz old_value, temp;
     double best_score = 0;
@@ -691,7 +837,7 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val
 
     for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
         mk_flip(srt, old_value, j, temp);
-        what_if(e, fd, temp, best_score, best_value, i);
+        what_if(g, e, fd, temp, best_score, best_value, i);
     }
 
     m_mpz_manager.del(old_value);
@@ -701,15 +847,15 @@ double sls_engine::find_best_move_local(expr * e, func_decl * fd, mpz & best_val
 }
 
 // second try to use intensification ... also not very effective
-bool sls_engine::handle_plateau(double old_score)
+bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
 {
-    unsigned sz = m_assertions.size();
+    unsigned sz = g->size();
 #if _BFS_
     unsigned new_const = m_stats.m_moves % sz;
 #else
     unsigned new_const = m_tracker.get_random_uint(16) % sz;
 #endif
-    expr * e = m_tracker.get_unsat_assertion(m_assertions, sz, new_const);
+    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
     if (!e)
         return 0;
 
@@ -726,12 +872,12 @@ bool sls_engine::handle_plateau(double old_score)
 
     for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
     {
-        new_score = find_best_move_local(q, fd, new_value, i);
+        new_score = find_best_move_local(g, q, fd, new_value, i);
 
         m_stats.m_moves++;
         m_stats.m_flips++;
 
-        global_score = incremental_score(fd, new_value);
+        global_score = incremental_score(g, fd, new_value);
         local_score = m_tracker.get_score(q);
 
         SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
@@ -744,7 +890,7 @@ bool sls_engine::handle_plateau(double old_score)
 }
 
 // main search loop
-lbool sls_engine::search() {
+lbool sls_engine::search(goal_ref const & g) {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
@@ -752,8 +898,15 @@ lbool sls_engine::search() {
     move_type move;
     unsigned plateau_cnt = 0;
 
-    score = rescore();
-    unsigned sz = m_assertions.size();
+    score = rescore(g);
+    unsigned sz = g->size();
+
+    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
+    tout << "Score distribution:";
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
+    tout << " TOP: " << score << std::endl;);
+
 #if _PERC_STICKY_
     expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
@@ -767,9 +920,18 @@ lbool sls_engine::search() {
 #else
     while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
 #endif
+        //if (m_stats.m_stopwatch.get_current_seconds() > 10.0)
+        //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);}
+
         checkpoint();
         m_stats.m_moves++;
 
+#if _UCT_FORGET_
+        //if (m_stats.m_moves % sz == 0)
+        if (m_stats.m_moves % _UCT_FORGET_ == 0)
+            m_tracker.uct_forget(g);
+#endif
+
 #if _REAL_RS_ || _REAL_PBFS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
@@ -779,13 +941,14 @@ lbool sls_engine::search() {
         if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
             e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #else
-        expr * e = m_tracker.get_unsat_assertion(m_assertions, m_stats.m_moves);
+        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
 #endif
         if (!e)
         {
             res = l_true;
             goto bailout;
         }
+        //ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_only(e);
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
 #else
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
@@ -818,13 +981,69 @@ lbool sls_engine::search() {
 #endif       
         old_score = score;
         new_const = (unsigned)-1;
+        move = MV_FLIP;
+        new_bit = 0;
 
 #if _VNS_
         score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
+        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
 
+#if _VNS_MC_ > _VNS_REPICK_
+#if _VNS_MC_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+#endif
+#if _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+#endif
+#endif
+
+#if _VNS_MC_ < _VNS_REPICK_
+#if _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+#endif
+#if _VNS_MC_
+        if (new_const == static_cast<unsigned>(-1))
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+#endif
+#endif
+
+#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_
+        if (new_const == static_cast<unsigned>(-1)) {
+            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
+                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
+            else {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                {
+                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
+                }
+            }
+        }        
+#endif
+
+
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
             plateau_cnt++;
@@ -839,25 +1058,52 @@ lbool sls_engine::search() {
                 mk_random_move(to_evaluate);
             else
 #endif
-#if _REPICK_
-                m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
+#if _REPICK_ == 1
+                m_evaluator.randomize_local(g, m_stats.m_moves);
+#elif _REPICK_ == 2
+            {
+                expr * q = m_tracker.get_new_unsat_assertion(g, e);
+                if (q)
+                    m_evaluator.randomize_local(q);
+                else
+                    m_evaluator.randomize_local(e);
+            }
 #else
-                m_evaluator.randomize_local(to_evaluate);
+                m_evaluator.randomize_local_n(g, to_evaluate);
+                //m_evaluator.randomize_local(to_evaluate);
 #endif
 #endif
 
 #if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / m_assertions.size();
+            score = m_tracker.get_top_sum() / g->size();
 #else
             score = top_score(g);
 #endif
+
+#if _PAWS_
+            for (unsigned i = 0; i < sz; i++)
+            {
+                expr * q = g->form(i);
+                if (m_tracker.get_random_uint(16) % 100 < _PAWS_)
+                {
+                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
+                        m_tracker.decrease_weight(q);
+                }
+                else
+                {
+                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
+                        m_tracker.increase_weight(q);
+                }
+            }
+#endif
+
         }
         else {
             func_decl * fd = to_evaluate[new_const];
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
             score = serious_score(g, fd, new_value);
 #else
-            score = incremental_score(fd, new_value);
+            score = incremental_score(g, fd, new_value);
 #endif
         }
     }
@@ -868,20 +1114,19 @@ bailout:
     return res;
 }
 
-#if 0 // Old code.
 // main search loop
-lbool sls_engine::search_old() {
+lbool sls_engine::search_old(goal_ref const & g) {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
     unsigned new_const = (unsigned)-1, new_bit = 0;
     mpz new_value;
     move_type move;
 
-    score = rescore();
+    score = rescore(g);
     TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
     tout << "Score distribution:";
-    for (unsigned i = 0; i < m_assertions.size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
+    for (unsigned i = 0; i < g->size(); i++)
+        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
     tout << " TOP: " << score << std::endl;);
 
     unsigned plateau_cnt = 0;
@@ -927,7 +1172,7 @@ lbool sls_engine::search_old() {
             old_score = score;
             new_const = (unsigned)-1;
 
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions, m_stats.m_moves);
+            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
             if (!to_evaluate.size())
             {
                 res = l_true;
@@ -938,22 +1183,22 @@ lbool sls_engine::search_old() {
                 tout << to_evaluate[i]->get_name() << std::endl;);
 
 #if _VNS_
-            score = find_best_move_vns(to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #else
-            score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
+            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
 #endif
             if (new_const == static_cast<unsigned>(-1)) {
                 TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
-                for (unsigned i = 0; i < m_assertions.size(); i++) {
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
-                        tout << mk_ismt2_pp(m_assertions[i], m_manager) << std::endl;
+                for (unsigned i = 0; i < g->size(); i++) {
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
+                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
                 });
 
                 TRACE("sls_max", m_tracker.show_model(tout);
                 tout << "Scores: " << std::endl;
-                for (unsigned i = 0; i < m_assertions.size(); i++)
-                    tout << mk_ismt2_pp(m_assertions[i], m_manager) << " ---> " <<
-                    m_tracker.get_score(m_assertions[i]) << std::endl;);
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
+                    m_tracker.get_score(g->form(i)) << std::endl;);
                 // Andreas: If new_const == -1, shouldn't score = old_score anyway?
                 score = old_score;
             }
@@ -991,15 +1236,15 @@ lbool sls_engine::search_old() {
                 case MV_DIV2: m_stats.m_div2s++; break;
                 }
 
-#if _REAL_RS_ || _REAL_PBFS_
-                score = serious_score(fd, new_value);
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
+                score = serious_score(g, fd, new_value);
 #else
-                score = incremental_score(fd, new_value);
+                score = incremental_score(g, fd, new_value);
 #endif
 
                 TRACE("sls", tout << "Score distribution:";
-                for (unsigned i = 0; i < m_assertions.size(); i++)
-                    tout << " " << std::setprecision(3) << m_tracker.get_score(m_assertions[i]);
+                for (unsigned i = 0; i < g->size(); i++)
+                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
                 tout << " TOP: " << score << std::endl;);
             }
 
@@ -1008,8 +1253,8 @@ lbool sls_engine::search_old() {
                 // score could theoretically be imprecise.
                 // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
                 bool all_true = true;
-                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1040,17 +1285,17 @@ lbool sls_engine::search_old() {
             TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
 #if _INTENSIFICATION_
             handle_plateau(g, score);
-            //handle_plateau();
+            //handle_plateau(g);
 #else
-            m_evaluator.randomize_local(m_assertions, m_stats.m_moves);
+            m_evaluator.randomize_local(g, m_stats.m_moves);
 #endif
-            //mk_random_move();
-            score = top_score();
+            //mk_random_move(g);
+            score = top_score(g);
 
             if (score >= 1.0) {
                 bool all_true = true;
-                for (unsigned i = 0; i < m_assertions.size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(m_assertions[i])))
+                for (unsigned i = 0; i < g->size() && all_true; i++)
+                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
                         all_true = false;
                 if (all_true) {
                     res = l_true; // sat
@@ -1067,17 +1312,6 @@ bailout:
 
     return res;
 }
-#endif
-
-void sls_engine::init_tracker() {
-#if _WEIGHT_DIST_ == 4
-    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-    m_tracker.initialize(m_assertions);
-}
 
 void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     if (g->inconsistent()) {
@@ -1087,9 +1321,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
-    for (unsigned i = 0; i < g->size(); i++)
-        assert_expr(g->form(i));    
-
     verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
     verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
     verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
@@ -1100,7 +1331,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
     verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
     verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
+    verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl;
+    verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl;
     verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
+    verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl;
+    verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl;
+    verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl;
+    verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl;
+    verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl;
     verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
     verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
     verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
@@ -1111,6 +1349,8 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
     verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
     verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
+    verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
+    verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
     verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
     verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
     verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
@@ -1125,9 +1365,36 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
     verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;    
+    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-    lbool res = operator()();
+#if _WEIGHT_DIST_ == 4
+    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
+#endif
+#if _WEIGHT_TOGGLE_
+    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
+#endif
+    m_tracker.initialize(g);
+    lbool res = l_undef;
+
+    m_restart_limit = _RESTART_LIMIT_;
+
+    do {
+        checkpoint();
+
+        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+        res = search(g);
+
+        if (res == l_undef)
+        {
+#if _RESTART_INIT_
+            m_tracker.randomize(g);
+#else
+            m_tracker.reset(g);
+#endif
+        }
+    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
+
+    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
 
     if (res == l_true) {
         report_tactic_progress("Number of flips:", m_stats.m_moves);
@@ -1149,38 +1416,13 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         mc = 0;
 }
 
-lbool sls_engine::operator()() {
-    init_tracker();
-    lbool res = l_undef;
-
-    m_restart_limit = _RESTART_LIMIT_;
-
-    do {
-        checkpoint();
-
-        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search();
-
-        if (res == l_undef)
-        {
-#if _RESTART_INIT_
-            m_tracker.randomize();
-#else
-            m_tracker.reset(m_assertions);
-#endif
-        }
-    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-
-    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-    
-    return res;
-}
-
 unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_limit)
     {
-#if _RESTART_SCHEME_ == 4
+#if _RESTART_SCHEME_ == 5
+        m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+#elif _RESTART_SCHEME_ == 4
         m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
         m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
@@ -1188,9 +1430,11 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
 #elif _RESTART_SCHEME_ == 1
         if (m_stats.m_restarts & 1)
+        //if (m_stats.m_restarts % 3 == 2)
             m_restart_limit += _RESTART_LIMIT_;
         else
             m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
+            //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_;
 #else
         m_restart_limit += _RESTART_LIMIT_;
 #endif
@@ -1201,4 +1445,4 @@ unsigned sls_engine::check_restart(unsigned curr_value)
         return 0;
     }
     return 1;
-}
+}
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index c6e3af155..902c6b7a0 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,7 +22,6 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
-#include"goal.h"
 
 #include"sls_compilation_settings.h"
 #include"sls_tracker.h"
@@ -72,7 +71,6 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
-    ptr_vector<expr> m_assertions;
 
     unsigned		m_restart_limit;
     unsigned        m_max_restarts;
@@ -94,12 +92,11 @@ public:
 
     void updt_params(params_ref const & _p);
 
-    void assert_expr(expr * e) { m_assertions.push_back(e); }
-
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(model & mdl);
+    bool full_eval(goal_ref const & g, model & mdl);
+    
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
     void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
@@ -107,48 +104,66 @@ public:
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
 
-    void init_tracker(void);
+    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
 
-    lbool search(void);    
+    double find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+
+    double find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value);
+
+    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
+                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    
+    
+    
+    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
+                 double & best_score, mpz & best_value, unsigned i);
+    
+    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
+    
+
+    lbool search(goal_ref const & g);    
 
-    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
+    lbool search_old(goal_ref const & g);
     double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
-    bool what_if(expr * e, func_decl * fd, const mpz & temp,
-                 double & best_score, mpz & best_value, unsigned i);
+
+    bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+                 double & best_score, unsigned & best_const, mpz & best_value);
+    double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value);
+
     bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                        double & best_score, unsigned & best_const, mpz & best_value);
 
-    double top_score();
-    double rescore();
-    double serious_score(func_decl * fd, const mpz & new_value);
-    double incremental_score(func_decl * fd, const mpz & new_value);
+    double top_score(goal_ref const & g);
+    double rescore(goal_ref const & g);
+    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
 
 #if _EARLY_PRUNE_
-    double incremental_score_prune(func_decl * fd, const mpz & new_value);
+    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
 #endif
-    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    double find_best_move_local(expr * e, func_decl * fd, mpz & best_value, unsigned i);
-    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
-    double find_best_move_vns(ptr_vector<func_decl> & to_evaluate, double score,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);    
-    void mk_random_move(ptr_vector<func_decl> & unsat_constants);
-    void mk_random_move();
 
-    bool handle_plateau(void);
-    bool handle_plateau(double old_score);
+    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+
+    void mk_random_move(ptr_vector<func_decl> & unsat_constants);
+    void mk_random_move(goal_ref const & g);
+
+    bool handle_plateau(goal_ref const & g);
+    bool handle_plateau(goal_ref const & g, double old_score);
 
     inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
+#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 7638ba5f4..78f2cb79a 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -575,7 +575,7 @@ public:
 #if _CACHE_TOP_SCORE_
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
@@ -584,12 +584,13 @@ public:
                 new_score = m_tracker.score(cur);
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
+
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -634,7 +635,7 @@ public:
 #if _CACHE_TOP_SCORE_
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
@@ -643,12 +644,12 @@ public:
                 new_score = m_tracker.score(cur);
                 //if (!m_tracker.has_uplinks(cur))
                 if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
 #else
                 m_tracker.set_score(cur, m_tracker.score(cur));
 #endif
-#endif			
+#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
@@ -683,7 +684,7 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         run_serious_update(max_depth);
 #else
         run_update(max_depth);
@@ -729,14 +730,16 @@ public:
 #if _CACHE_TOP_SCORE_
             //if (!m_tracker.has_uplinks(cur))
             if (m_tracker.is_top_expr(cur))
-                m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
 #endif
             prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
             if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
+            //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
                 pot_benefits = 1;
             if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
+            //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
                 pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
@@ -771,7 +774,7 @@ public:
                     new_score = m_tracker.score(cur); 
                     //if (!m_tracker.has_uplinks(cur))
                     if (m_tracker.is_top_expr(cur))
-                        m_tracker.adapt_top_sum(new_score, m_tracker.get_score(cur));
+                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
 #else
                     m_tracker.set_score(cur, m_tracker.score(cur));
@@ -858,6 +861,104 @@ public:
     }
 #endif
 
+    unsigned run_update_bool_prune_new(unsigned cur_depth) {
+        expr_fast_mark1 visited;
+
+        double prune_score, new_score;
+        unsigned pot_benefits = 0;
+        SASSERT(cur_depth < m_traversal_stack_bool.size());
+ 
+        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+
+        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
+            expr * cur = cur_depth_exprs[i];
+
+            new_score = m_tracker.score(cur); 
+            //if (!m_tracker.has_uplinks(cur))
+            if (m_tracker.is_top_expr(cur))
+                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+            prune_score = m_tracker.get_score_prune(cur);
+            m_tracker.set_score(cur, new_score);
+
+            if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
+                pot_benefits = 1;
+            if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
+                pot_benefits = 1;
+
+            if (m_tracker.has_uplinks(cur)) {
+                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                for (unsigned j = 0; j < ups.size(); j++) {
+                    expr * next = ups[j];
+                    unsigned next_d = m_tracker.get_distance(next);
+                    SASSERT(next_d < cur_depth);
+                    if (!visited.is_marked(next)) {
+                        m_traversal_stack_bool[next_d].push_back(next);
+                        visited.mark(next);
+                    }
+                }
+            }
+            else
+            {
+            }
+        }
+
+        cur_depth_exprs.reset();
+        cur_depth--;
+ 
+        while (cur_depth != static_cast<unsigned>(-1)) {
+            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
+            if (pot_benefits)
+            {
+                unsigned cur_size = cur_depth_exprs.size();
+                for (unsigned i = 0; i < cur_size; i++) {
+                    expr * cur = cur_depth_exprs[i];
+
+                    new_score = m_tracker.score(cur); 
+                    //if (!m_tracker.has_uplinks(cur))
+                    if (m_tracker.is_top_expr(cur))
+                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                    m_tracker.set_score(cur, new_score);
+                    if (m_tracker.has_uplinks(cur)) {
+                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
+                        for (unsigned j = 0; j < ups.size(); j++) {
+                            expr * next = ups[j];
+                            unsigned next_d = m_tracker.get_distance(next);
+                            SASSERT(next_d < cur_depth);
+                            if (!visited.is_marked(next)) {
+                                m_traversal_stack_bool[next_d].push_back(next);
+                                visited.mark(next);
+                            }
+                        }
+                    }
+                }
+            }
+            cur_depth_exprs.reset();
+            cur_depth--;
+        }
+
+        return pot_benefits;
+    }
+
+    unsigned update_prune_new(func_decl * fd, const mpz & new_value) {
+        m_tracker.set_value(fd, new_value);
+        expr * ep = m_tracker.get_entry_point(fd);
+        unsigned cur_depth = m_tracker.get_distance(ep);
+
+        if (m_traversal_stack_bool.size() <= cur_depth)
+            m_traversal_stack_bool.resize(cur_depth+1);
+        if (m_traversal_stack.size() <= cur_depth) 
+                m_traversal_stack.resize(cur_depth+1);
+
+        if (m_manager.is_bool(ep))
+            m_traversal_stack_bool[cur_depth].push_back(ep);
+        else
+        {
+            m_traversal_stack[cur_depth].push_back(ep);
+            run_update_prune(cur_depth);
+        }
+        return run_update_bool_prune_new(cur_depth);
+    }
+
     void randomize_local(ptr_vector<func_decl> & unsat_constants) {
         // Randomize _all_ candidates:
 
@@ -901,7 +1002,7 @@ public:
         mpz temp = m_tracker.get_random(fd->get_range());
 #endif
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         serious_update(fd, temp);
 #else
         update(fd, temp);
@@ -922,9 +1023,36 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-    void randomize_local(ptr_vector<expr> const & as, unsigned int flip) {
-        randomize_local(m_tracker.get_unsat_constants(as, flip));
+    void randomize_local(goal_ref const & g, unsigned int flip) {
+        randomize_local(m_tracker.get_unsat_constants(g, flip));
     } 
+
+    void randomize_local_n(goal_ref const & g, ptr_vector<func_decl> & unsat_constants) {
+        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
+        func_decl * fd = unsat_constants[r];
+        sort * srt = fd->get_range();
+        unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); 
+        mpz max_val = m_tracker.get_random(srt);
+        update(fd, max_val);
+        double max_score = m_tracker.get_top_sum() / g->size();
+        mpz temp_val;
+        double temp_score;
+        for (unsigned i = 1; i < 2; i++)
+        //for (unsigned i = 1; i < bv_sz; i++)
+        {
+            m_mpz_manager.set(temp_val, m_tracker.get_random(srt));
+            update(fd, temp_val);
+            temp_score = m_tracker.get_top_sum() / g->size();
+            if (temp_score > max_score)
+            {
+                m_mpz_manager.set(max_val, temp_val);
+                max_score = temp_score;
+            }
+        }
+        update(fd, max_val);
+        m_mpz_manager.del(temp_val);
+        m_mpz_manager.del(max_val);
+    }
 };
 
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index b2b7035e0..0b6b01e7c 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -1509,14 +1509,14 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                         mk_max_bv_sharing_tactic(m),
                         // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
                         //mk_ctx_simplify_tactic(m, ctx_p),
-                        // Andreas: This one at least eliminates top level duplicates ...
+                        // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance!
                         //mk_simplify_tactic(m),
-                        // Andreas: How does a NNF actually look like? Can it contain ITE operators?
                         mk_nnf_tactic(m, p));
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
     tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
+//    tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 537492213..87c90f1f8 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,9 +20,7 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"for_each_expr.h"
-#include"ast_smt2_pp.h"
-#include"bv_decl_plugin.h"
+#include"goal.h"
 #include"model.h"
 
 #include"sls_compilation_settings.h"
@@ -88,12 +86,17 @@ private:
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
 #endif
+#if _PAWS_
+    obj_map<expr, unsigned> m_weights;
+    //obj_map<expr, double> m_weights;
+#endif
 #if _CACHE_TOP_SCORE_
     double				  m_top_sum;
 #endif
 #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     double				  m_weight_dist_factor;
 #endif
+    unsigned              m_equal_scores;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -113,15 +116,52 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+    unsigned get_formula_size() {
+        return m_scores.size();
+    }
+
+    double get_avg_bw(goal_ref const & g) {
+        double sum = 0.0;
+        unsigned count = 0;
+
+        for (unsigned i = 0; i < g->size(); i++)
+        {
+            m_temp_constants.reset();
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(g->form(i));
+            unsigned sz = this_decls.size();
+            for (unsigned i = 0; i < sz; i++) {
+                func_decl * fd = this_decls[i];
+                m_temp_constants.push_back(fd);
+                sort * srt = fd->get_range();
+                sum += (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);         
+                count++;
+            }
+        }
+
+        return sum / count;   
+    }
+
 #if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
     inline void set_weight_dist_factor(double val) {
         m_weight_dist_factor = val;
     }
 #endif
 
+    void reset_equal_scores() {
+        m_equal_scores = 1;
+    }
+
+    unsigned inc_equal_scores() {
+        return ++m_equal_scores;
+    }
+
 #if _CACHE_TOP_SCORE_
-    inline void adapt_top_sum(double add, double sub) {
+    inline void adapt_top_sum(expr * e, double add, double sub) {
+#if _PAWS_
+        m_top_sum += m_weights.find(e) * (add - sub);
+#else
         m_top_sum += add - sub;
+#endif
     }
 
     inline void set_top_sum(double new_score) {
@@ -278,19 +318,21 @@ public:
     }
 #endif
 
-    void uct_forget(ptr_vector<expr> & as) {
+#if _UCT_
+    void uct_forget(goal_ref const & g) {
         expr * e;
         unsigned touched_old, touched_new;
 
-        for (unsigned i = 0; i < as.size(); i++)
+        for (unsigned i = 0; i < g->size(); i++)
         {
-            e = as[i];
+            e = g->form(i);
             touched_old = m_scores.find(e).touched;
             touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
             m_scores.find(e).touched = touched_new;
             m_touched += touched_new - touched_old;
         }
     }
+#endif
 
     void initialize(app * n) {
         // Build score table
@@ -367,12 +409,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(ptr_vector<expr> const & as) {
+    void calculate_expr_distances(goal_ref const & g) {
         // precondition: m_scores is set up.
-        unsigned sz = as.size();
+        unsigned sz = g->size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(as[i]));
+            stack.push_back(to_app(g->form(i)));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -420,12 +462,12 @@ public:
         quick_for_each_expr(ffd_proc, visited, e);
     }
 
-    void initialize(ptr_vector<expr> const & as) {
+    void initialize(goal_ref const & g) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = as.size();
+        unsigned sz = g->size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = as[i];
+            expr * e = g->form(i);
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
             else
@@ -440,7 +482,7 @@ public:
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = as[i];
+            expr * e = g->form(i);
             // Andreas: Maybe not fully correct.
 #if _FOCUS_ == 2 || _INTENSIFICATION_
             initialize_recursive(e);
@@ -452,7 +494,7 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(as);
+        calculate_expr_distances(g);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
@@ -465,16 +507,49 @@ public:
         //}
 #endif
 
+#if _PAWS_
+        for (unsigned i = 0; i < sz; i++)
+        {
+            expr * e = g->form(i);
+        	if (!m_weights.contains(e))
+        		m_weights.insert(e, _PAWS_INIT_);
+        }
+#endif
+
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-            setup_occs(as[i]);
+            setup_occs(g->form(i));
 #endif
 
 #if _UCT_
-        m_touched = _UCT_INIT_ ? as.size() : 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
 #endif
     }
 
+#if _PAWS_
+    void increase_weight(expr * e)
+    {
+        //printf("Increasing %d to", m_weights.find(e));
+        m_weights.find(e)++;
+        //m_weights.find(e) *= 1.1;
+        //printf(" %d\n", m_weights.find(e));
+    }
+
+    void decrease_weight(expr * e)
+    {
+        unsigned old_weight = m_weights.find(e);
+        m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_;
+        //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1;
+        //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e));
+    }
+
+    unsigned get_weight(expr * e)
+    //double get_weight(expr * e)
+    {
+        return m_weights.find(e);
+    }
+#endif
+
 #if _REAL_RS_ || _REAL_PBFS_
     void make_assertion(expr * e)
     {
@@ -608,7 +683,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(ptr_vector<expr> const & as) {
+    void randomize(goal_ref const & g) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -622,13 +697,13 @@ public:
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? as.size() : 1;
-        for (unsigned i = 0; i < as.size(); i++)
-            m_scores.find(as[i]).touched = 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
 #endif
     }              
 
-    void reset(ptr_vector<expr> const & as) {
+    void reset(goal_ref const & g) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -638,9 +713,9 @@ public:
         }
 
 #if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? as.size() : 1;
-        for (unsigned i = 0; i < as.size(); i++)
-            m_scores.find(as[i]).touched = 1;
+        m_touched = _UCT_INIT_ ? g->size() : 1;
+        for (unsigned i = 0; i < g->size(); i++)
+            m_scores.find(g->form(i)).touched = 1;
 #endif
     }              
 
@@ -765,6 +840,7 @@ public:
             const mpz & v1 = get_value(arg1);
             
             if (negated) {                    
+                //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0;
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << std::endl; );
@@ -811,40 +887,209 @@ public:
             SASSERT(a->get_num_args() == 2);
             const mpz & x = get_value(a->get_arg(0));
             const mpz & y = get_value(a->get_arg(1));
-            unsigned bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
+            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
 
             if (negated) {
                 if (m_mpz_manager.gt(x, y))
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(x, y, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+/*                  mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_gt = 0;
+                    unsigned curr_gt = 0;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 1;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 0;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
+                    m_mpz_manager.del(x_copy);
+                    m_mpz_manager.del(y_copy);*/
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);                            
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));                            
+                    double dbl = 1.0 - n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    m_mpz_manager.del(diff);
+#endif
+                }
+            }
+            else {
+                if (m_mpz_manager.le(x, y))                        
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(y, x, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
                     double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-                }
-            }
-            else {
-                if (m_mpz_manager.le(x, y))                        
+                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+/*                  mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_le = 1;
+                    unsigned curr_le = 1;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 0;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 1;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));
-                    double dbl = n.get_double();
+                    double dbl = 1.0 - n.get_double();
                     res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
             }
             TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                     m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
         }
-        else if (m_bv_util.is_bv_sle(n)) { // x <= y
+/*        else if (m_bv_util.is_bv_sle(n)) { // x <= y
+            app * a = to_app(n);
+            SASSERT(a->get_num_args() == 2);
+            const mpz & x = get_value(a->get_arg(0));
+            const mpz & y = get_value(a->get_arg(1));
+            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
+
+            mpz x_unsigned;
+            mpz y_unsigned;
+            const mpz & p = m_powers(bv_sz);
+            const mpz & p_half = m_powers(bv_sz-1);
+            if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } 
+            if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); }                 
+
+            if (negated) {
+                if (x_unsigned > y_unsigned)
+                    res = 1.0; 
+                else {
+                    mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_gt = 0;
+                    unsigned curr_gt = 0;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 1;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_gt = curr_gt;
+                            curr_gt = 0;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
+                    m_mpz_manager.del(x_copy);
+                    m_mpz_manager.del(y_copy);
+                }
+            }
+            else {
+                if (x_unsigned <= y_unsigned)                        
+                    res = 1.0; 
+                else {
+                    mpz x_copy, y_copy;
+                    m_mpz_manager.set(x_copy, x);
+                    m_mpz_manager.set(y_copy, y);
+                    unsigned lower_le = 1;
+                    unsigned curr_le = 1;
+                    int last_pos = -1;
+                    for (int i = 0; i < bv_sz; i++)
+                    {
+                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 0;
+                            last_pos = i;
+                        }
+                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
+                        {
+                            lower_le = curr_le;
+                            curr_le = 1;
+                            last_pos = i;
+                        }
+ 
+                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
+                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
+                    }
+
+                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);
+                }
+            }
+            TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
+                                    m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
+
+            m_mpz_manager.del(x_unsigned);
+            m_mpz_manager.del(y_unsigned);
+        }*/
+      else if (m_bv_util.is_bv_sle(n)) { // x <= y
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 2);
             mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0)));
@@ -857,31 +1102,61 @@ public:
 
             if (negated) {
                 if (x > y)
-                    res = 1.0;
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(x, y, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
+                    res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);
                     rational n(diff);
                     n /= p;
-                    double dbl = n.get_double();
-                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    double dbl = 1.0 - n.get_double();
+                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
             else {
                 if (x <= y)
-                    res = 1.0;
+                {
+                    /*mpz diff;
+                    m_mpz_manager.sub(y, x, diff);
+                    m_mpz_manager.inc(diff);                            
+                    rational n(diff);
+                    n /= rational(m_powers(bv_sz));                            
+                    double dbl = n.get_double();
+                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
+                    m_mpz_manager.del(diff);
+                    res = 1.0 + 0.5 * dbl;*/
+                    res = 1.0; 
+                }
                 else {
+                    //res = (bv_sz - 1.0) / bv_sz;
+#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
+                    SASSERT(!m_mpz_manager.is_neg(diff));
                     rational n(diff);
                     n /= p;
-                    double dbl = n.get_double();
+                    double dbl = 1.0 - n.get_double();
                     res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
                     m_mpz_manager.del(diff);
+#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
@@ -1031,13 +1306,13 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as, unsigned sz) {
+    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
         if (sz == 1)
             return get_constants();
         m_temp_constants.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * q = as[i];
+            expr * q = g->form(i);
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -1051,22 +1326,22 @@ public:
         return m_temp_constants;
     }
 
-    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
+    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
             for (unsigned i = pos; i < sz; i++) {
-                expr * q = as[i];
+                expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             for (unsigned i = 0; i < pos; i++) {
-                expr * q = as[i];
+                expr * q = g->form(i);
                 if (m_mpz_manager.neq(get_value(q), m_one))
                     return q;
             }
             return 0;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_walksat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
-            expr * q = get_unsat_assertion(as, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
+            expr * q = get_unsat_assertion(g, sz, pos);
             // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
             if (!q)
                 return m_temp_constants;
@@ -1143,20 +1418,66 @@ public:
             return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_crsat(ptr_vector<expr> const & as, unsigned sz, unsigned int pos) {
-        expr * q = get_unsat_assertion(as, sz, pos);
+    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
+        expr * q = get_unsat_assertion(g, sz, pos);
         if (!q)
             return m_temp_constants;
 
         return go_deeper(q);
     }
 
-    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as, unsigned int flip) {
-        unsigned sz = as.size();
+    void go_deeper_only(expr * e) {
+            //if (m_manager.is_bool(e)) {
+                if (m_manager.is_and(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    unsigned cnt_unsat = 0, pos = -1;
+                    for (unsigned int i = 0; i < sz; i++) {
+                        expr * q = args[i];
+                        if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+                        //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q);
+                    }
+                    go_deeper(args[pos]);
+                }
+                else if (m_manager.is_or(e)) {
+                    app * a = to_app(e);
+                    expr * const * args = a->get_args();
+                    unsigned int sz = a->get_num_args();
+                    for (unsigned int i = 0; i < sz; i++) {
+                        expr * q = args[i];
+                        go_deeper(q);
+                    }
+                }
+            //}
+                else
+                {
+            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
+            unsigned sz2 = this_decls.size();
+            for (unsigned j = 0; j < sz2; j++) {
+                func_decl * fd = this_decls[j];
+                if (!m_temp_constants.contains(fd))
+                    m_temp_constants.push_back(fd);
+            }
+                }
+    }
+
+    ptr_vector<func_decl> & get_unsat_constants_only(expr * e) {
+            if (e && !m_temp_constants.size())
+                go_deeper_only(e);
+
+            return m_temp_constants;
+    }
+
+    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
 
         if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(as[0]), m_one))
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            {
+                m_temp_constants.reset();
                 return m_temp_constants;
+            }
             else
                 return get_constants();
         }
@@ -1169,11 +1490,12 @@ public:
 #if _PROBABILISTIC_UCT_
             double sum_score = 0.0;
             unsigned start_index = get_random_uint(16) % sz;
-            
+
             for (unsigned i = start_index; i < sz; i++)
             {
                 expr * e = g->form(i);
                 vscore = m_scores.find(e);
+
 #if _PROBABILISTIC_UCT_ == 2
                 double q = vscore.score * vscore.score; 
 #else
@@ -1203,7 +1525,7 @@ public:
 #else
             double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = as[i];
+                expr * e = g->form(i);
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
@@ -1221,12 +1543,12 @@ public:
                 return m_temp_constants;
 
 #if _UCT_ == 1 || _UCT_ == 3
-            m_scores.find(as[pos]).touched++;
+            m_scores.find(g->form(pos)).touched++;
             m_touched++;
 #elif _UCT_ == 2
-            m_scores.find(as[pos]).touched = flip; 
+            m_scores.find(g->form(pos)).touched = flip; 
 #endif
-            expr * e = as[pos];
+            expr * e = g->form(pos);
 //            expr * e = m_list_false[pos];
 
 #elif _BFS_ == 3
@@ -1304,12 +1626,15 @@ public:
         }
     }
     
+    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
+        unsigned sz = g->size();
 
-    expr * get_unsat_assertion(ptr_vector<expr> const & as, unsigned int flip) {
-        unsigned sz = as.size();
-
-        if (sz == 1)
-            return as[0];
+        if (sz == 1) {
+            if (m_mpz_manager.eq(get_value(g->form(0)), m_zero))
+                return g->form(0);
+            else
+                return 0;
+        }
 
         m_temp_constants.reset();
 #if _FOCUS_ == 1
@@ -1353,12 +1678,12 @@ public:
 #else
         double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = as[i];
+                expr * e = g->form(i);
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
 #if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
+            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
 #elif _UCT_ == 2
             double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
 #elif _UCT_ == 3
@@ -1371,13 +1696,13 @@ public:
             return 0;
 
 #if _UCT_ == 1 || _UCT_ == 3
-        m_scores.find(as[pos]).touched++;
+        m_scores.find(g->form(pos)).touched++;
         m_touched++;
 #elif _UCT_ == 2
         m_scores.find(g->form(pos)).touched = flip; 
 #endif
 //        return m_list_false[pos];
-        return as[pos];
+        return g->form(pos);
 
 #elif _BFS_ == 3
         unsigned int pos = -1;
@@ -1431,7 +1756,7 @@ public:
         unsigned int pos = get_random_uint(16) % sz;
         return get_unsat_assertion(g, sz, pos);
 #endif
-        return as[pos];
+        return g->form(pos);
 #elif _FOCUS_ == 2
 #if _BFS_
         unsigned int pos = flip % sz;
@@ -1441,6 +1766,23 @@ public:
         return get_unsat_constants_crsat(g, sz, pos);
 #endif
     }
+
+    expr * get_new_unsat_assertion(goal_ref const & g, expr * e) {
+        unsigned sz = g->size();
+
+        if (sz == 1)
+            return 0;
+
+        m_temp_constants.reset();
+
+        unsigned cnt_unsat = 0, pos = -1;
+        for (unsigned i = 0; i < sz; i++)
+            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i;	
+
+        if (pos == static_cast<unsigned>(-1))
+            return 0;
+        return g->form(pos);
+    }
 };
 
 #endif
\ No newline at end of file

From de028e7a30df593547b47262e98d9673f00adfa9 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 00:32:45 +0100
Subject: [PATCH 084/108] Almost cleaned up version.

---
 src/tactic/sls/sls_compilation_settings.h |  156 +--
 src/tactic/sls/sls_engine.cpp             | 1168 +++------------------
 src/tactic/sls/sls_engine.h               |   89 +-
 src/tactic/sls/sls_evaluator.h            |  262 +----
 src/tactic/sls/sls_tactic.cpp             |    6 +-
 src/tactic/sls/sls_tracker.h              |  904 ++--------------
 6 files changed, 315 insertions(+), 2270 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index d2b899dd8..9add78daa 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,167 +22,13 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
-// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
-#define _BFS_ 0
-
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
-#define _FOCUS_ 1
-
-// probability of choosing the same assertion again in the next step
-#define _PERC_STICKY_ 0
-
-// do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 0
-
-// shall we use additive weighting scheme?
-#define _PAWS_ 5
-#define _PAWS_INIT_ 40
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 1
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 100
-// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 2.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// should score of discunctions be calculated by multiplication of the inverse score rather than min?
-#define _SCORE_OR_MUL_ 0
-
-// do we use some kind of variable neighbourhood-search?
-// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
-#define _VNS_ 0
-
-// shall we check 2-bit flips in plateaus using Monte Carlo?
-#define _VNS_MC_ 0
-
-// how many 2-bit flips shall we try per bit?
-#define _VNS_MC_TRIES_ 1
-
-// shall we check another assertion if no improving step was found in the first one?
-#define _VNS_REPICK_ 0
-
-// what is the probability of doing so (percentage)?
-#define _VNS_PERC_ 100
-
-// do a decreasing move with percentage ...
-#define _INSIST_PERC_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no
-// 1 = yes, by multiplying it with some factor
-// 2 = yes, by squaring it
-// 3 = yes, by setting it to zero
-// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.5
-
-// shall we toggle the weight after each restart?
-#define _WEIGHT_TOGGLE_ 0
-
-// do we use intensification steps in local minima? if so, how many?
-#define _INTENSIFICATION_ 0
-#define _INTENSIFICATION_TRIES_ 0
-
-// what is the percentage of random moves in plateaus (instead of full randomization)?
-#define _PERC_PLATEAU_MOVES_ 0
-
-// shall we repick assertion when randomizing in a plateau or use the current one?
-// 0 = use old one, 1 = repick according to usual scheme, 2 = repick randomly and force different one
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 20.0
-
-// is uct clause selection probabilistic similar to variable selection in sparrow?
-// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
-#define _PROBABILISTIC_UCT_ 0
-
-// additive constants for probabilistic uct > 0
-#define _UCT_EPS_ 0.0001
-
-// shall we reset _UCT_ touched values after restart?
-#define _UCT_RESET_ 0
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 0
-
-// do we gradually reduce the touched values of _UCT_?
-#define _UCT_FORGET_ 0
-#define _UCT_FORGET_FACTOR_ 0.9
-
 // shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
-// shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 0
-
-// shall we try multiplication by 3?
-#define _USE_MUL3_ 0
-
-// shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 0
-
-// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 0
+#define _USE_ADDSUB_ 0
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
-#define _REAL_PBFS_ 0
-
-// how many bits do we neglect in each iteration?
-#define _SKIP_BITS_ 0
-
-// when randomizing local, what is the probability for changing a single bit?
-// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
-#define _PERC_CHANGE_ 0
-
-// do we use random steps for noise?
-// 0 = no, 1 = randomize local, 2 = make random move
-#define _TYPE_RSTEP_ 0
-
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
 
 // shall we use early pruning for incremental update?
 #define _EARLY_PRUNE_ 1
 
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-
-#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
-InvalidConfiguration;
-#endif
-#if (_PROBABILISTIC_UCT_ && !_UCT_)
-InvalidConfiguration;
-#endif
-#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
-InvalidConfiguration;
-#endif
-#if (_PERC_CHANGE_ == 50)
-InvalidConfiguration;
-#endif
-#if (_PERC_STICKY_ && !_FOCUS_)
-InvalidConfiguration;
-#endif
-
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 342e649af..c240a0c51 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -44,6 +44,7 @@ sls_engine::sls_engine(ast_manager & m, params_ref const & p) :
     m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers)
 {
     updt_params(p);
+    m_tracker.updt_params(p);
 }
 
 sls_engine::~sls_engine() {
@@ -52,20 +53,21 @@ sls_engine::~sls_engine() {
     m_mpz_manager.del(m_two);
 }
 
-double sls_engine::get_restart_armin(unsigned cnt_restarts)
-{
-    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-    //printf("armin: %f\n", pow(1.1, inner_id + 1));
-    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
-}    
-
 void sls_engine::updt_params(params_ref const & _p) {
     sls_params p(_p);
     m_produce_models = _p.get_bool("model", false);
-    m_max_restarts = p.restarts();
+    m_max_restarts = p.max_restarts();
     m_tracker.set_random_seed(p.random_seed());
-    m_plateau_limit = p.plateau_limit();
+    m_walksat = p.walksat();
+    m_walksat_repick = p.walksat_repick();
+    m_paws_sp = p.paws_sp();
+    m_wp = p.wp();
+    m_vns_mc = p.vns_mc();
+    m_vns_repick = p.vns_repick();
+
+    m_restart_base = p.restart_base();
+    m_restart_next = m_restart_base;
+    m_restart_init = p.restart_init();
 }
 
 void sls_engine::checkpoint() {
@@ -74,15 +76,15 @@ void sls_engine::checkpoint() {
     cooperate("sls");
 }
 
-bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
+bool sls_engine::full_eval(model & mdl) {
     bool res = true;
 
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz && res; i++) {
         checkpoint();
         expr_ref o(m_manager);
 
-        if (!mdl.eval(g->form(i), o, true))
+        if (!mdl.eval(m_assertions[i], o, true))
             exit(ERR_INTERNAL_FATAL);
 
         res = m_manager.is_true(o.get());
@@ -93,93 +95,58 @@ bool sls_engine::full_eval(goal_ref const & g, model & mdl) {
     return res;
 }
 
-double sls_engine::top_score(goal_ref const & g) {
-#if 0
-    double min = m_tracker.get_score(g->form(0));
-    unsigned sz = g->size();
-    for (unsigned i = 1; i < sz; i++) {
-        double q = m_tracker.get_score(g->form(i));
-        if (q < min) min = q;
-    }
-    TRACE("sls_top", tout << "Score distribution:";
-    for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(g->form(i));
-    tout << " MIN: " << min << std::endl;);
-    return min;
-#else
+double sls_engine::top_score() {
     double top_sum = 0.0;
-    unsigned sz = g->size();
+    unsigned sz = m_assertions.size();
     for (unsigned i = 0; i < sz; i++) {
-        expr * e = g->form(i);
+        expr * e = m_assertions[i];
         top_sum += m_tracker.get_score(e);
     }
 
     TRACE("sls_top", tout << "Score distribution:";
     for (unsigned i = 0; i < sz; i++)
-        tout << " " << m_tracker.get_score(g->form(i));
+        tout << " " << m_tracker.get_score(m_assertions[i]);
     tout << " AVG: " << top_sum / (double)sz << std::endl;);
 
-#if _CACHE_TOP_SCORE_
     m_tracker.set_top_sum(top_sum);
-#endif
 
     return top_sum / (double)sz;
-#endif
 }
 
-double sls_engine::rescore(goal_ref const & g) {
+double sls_engine::rescore() {
     m_evaluator.update_all();
     m_stats.m_full_evals++;
-    return top_score(g);
+    return top_score();
 }
 
-double sls_engine::serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
-#else
-    return top_score(g);
-#endif
+    return (m_tracker.get_top_sum() / m_assertions.size());
 }
 
-double sls_engine::incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
+double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-    return (m_tracker.get_top_sum() / g->size());
-#else
-    return top_score(g);
-#endif
+    return (m_tracker.get_top_sum() / m_assertions.size());
 }
 
-double sls_engine::incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-#if _EARLY_PRUNE_
+double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
-        return (m_tracker.get_top_sum() / g->size());
-#else
-        return top_score(g);
-#endif
-    else
-        return 0.0;
-#else
-    NOT_IMPLEMENTED_YET();
-#endif
-}
-
-double sls_engine::incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-    m_stats.m_incr_evals++;
-    if (m_evaluator.update_prune_new(fd, new_value))
-        return (m_tracker.get_top_sum() / g->size());
+        return (m_tracker.get_top_sum() / m_assertions.size());
     else
         return 0.0;
 }
 
 // checks whether the score outcome of a given move is better than the previous score
-bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                double & best_score, unsigned & best_const, mpz & best_value) {
+bool sls_engine::what_if(
+    func_decl * fd, 
+    const unsigned & fd_inx, 
+    const mpz & temp,
+    double & best_score, 
+    unsigned & best_const, 
+    mpz & best_value) {
 
 #ifdef Z3DEBUG
     mpz old_value;
@@ -187,9 +154,9 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
 #endif
 
 #if _EARLY_PRUNE_
-    double r = incremental_score_prune(g, fd, temp);
+    double r = incremental_score_prune(fd, temp);
 #else
-    double r = incremental_score(g, fd, temp);
+    double r = incremental_score(fd, temp);
 #endif   
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
@@ -198,7 +165,7 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
     m_mpz_manager.del(old_value);
 #endif
 
-    //if (r >= best_score) {
+    // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
         m_tracker.reset_equal_scores();
         best_score = r;
@@ -206,45 +173,6 @@ bool sls_engine::what_if(goal_ref const & g, func_decl * fd, const unsigned & fd
         m_mpz_manager.set(best_value, temp);
         return true;
     }
-    /*else if (r == best_score) {
-        if (m_tracker.get_random_uint(16) % m_tracker.inc_equal_scores() == 0)
-        {
-            best_score = r;
-            best_const = fd_inx;
-            m_mpz_manager.set(best_value, temp);
-            return true;
-        }
-    }*/
-
-    return false;
-}
-
-bool sls_engine::what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                double & best_score, unsigned & best_const, mpz & best_value) {
-
-    double r = incremental_score_prune_new(g, fd, temp);
-
-    if (r >= best_score) {
-        best_score = r;
-        best_const = fd_inx;
-        m_mpz_manager.set(best_value, temp);
-        return true;
-    }
-
-    return false;
-}
-
-// same as what_if, but only applied to the score of a specific atom, not the total score
-bool sls_engine::what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                    double & best_score, unsigned & best_const, mpz & best_value) {
-    m_evaluator.update(fd, temp);
-    double r = m_tracker.get_score(e);
-    if (r >= best_score) {
-        best_score = r;
-        best_const = fd_inx;
-        m_mpz_manager.set(best_value, temp);
-        return true;
-    }
 
     return false;
 }
@@ -261,22 +189,6 @@ void sls_engine::mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value,
 
 }
 
-// Andreas: do we really need all those temporary mpzs?
-void sls_engine::mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-    mpz temp, mask, mask2;
-    m_mpz_manager.mul(old_value, m_two, temp);
-    m_mpz_manager.set(mask, m_powers(bv_sz));
-    m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-    m_mpz_manager.bitwise_and(temp, mask2, result);
-    m_mpz_manager.del(temp);
-    m_mpz_manager.del(mask);
-    m_mpz_manager.del(mask2);
-}
-
-void sls_engine::mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-    m_mpz_manager.div(old_value, m_two, result);
-}
-
 void sls_engine::mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
     unsigned shift;
     m_mpz_manager.add(old_value, m_one, incremented);
@@ -334,7 +246,7 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         // inversion doesn't make sense, let's do a flip instead.
         if (mt == MV_INV) mt = MV_FLIP;
 #else
-        mt = MV_FLIP;
+        move_type mt = MV_FLIP;
 #endif
         unsigned bit = 0;
 
@@ -373,216 +285,40 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout););
     }
 
-    m_evaluator.update(fd, new_value);
+    m_evaluator.serious_update(fd, new_value);
     m_mpz_manager.del(new_value);
 }
 
-void sls_engine::mk_random_move(goal_ref const & g) {
-    mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));
-}
-
-// will use VNS to ignore some possible moves and increase the flips per second
-double sls_engine::find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-    mpz old_value, temp;
-    unsigned bv_sz, max_bv_sz = 0;
-    double new_score = score;
-
-    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
-        func_decl * fd = to_evaluate[i];
-        sort * srt = fd->get_range();
-        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-            if (!m_mpz_manager.is_even(old_value)) {
-                // for odd values, try +1
-                mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_INC;
-            }
-            else {
-                // for even values, try -1
-                mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_DEC;
-            }
-
-            // try inverting
-            mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_INV;
-
-            // try to flip lsb
-            mk_flip(srt, old_value, 0, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                new_bit = 0;
-                move = MV_FLIP;
-            }
-        }
-
-        // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
-        SASSERT(check == score);
-    }
-
-    // we can either check the condition once in the beginning or check it repeatedly after every bit
-#if _VNS_ == 1
-    for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
-#else
-    if (new_score <= score)
-        for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
-#endif
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // What would happen if we flipped bit #j ?                
-                if (j < bv_sz)
-                {
-                    mk_flip(srt, old_value, j, temp);
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-    return new_score;
-}
-
-double sls_engine::find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-    mpz old_value, temp;
-    unsigned bv_sz, max_bv_sz = 0;
-    double new_score = score;
-
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
-        func_decl * fd = to_evaluate[i];
-        sort * srt = fd->get_range();
-        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-        if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-            // try inverting
-            mk_inv(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_INV;
-
-            if (!m_mpz_manager.is_even(old_value)) {
-                // for odd values, try +1
-                mk_inc(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_INC;
-            }
-            else {
-                // for even values, try -1
-                mk_dec(bv_sz, old_value, temp);
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_DEC;
-            }
-
-            // try to flip lsb
-            mk_flip(srt, old_value, 0, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                new_bit = 0;
-                move = MV_FLIP;
-            }
-        }
-
-        // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
-        SASSERT(check == score);
-    }
-
-    for (unsigned j = 1; j < max_bv_sz; j++)
-    {
-        for (unsigned i = 0; i < to_evaluate.size(); i++) {
-            func_decl * fd = to_evaluate[i];
-            sort * srt = fd->get_range();
-            bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-            // What would happen if we flipped bit #j ?                
-            if (j < bv_sz)
-            {
-                mk_flip(srt, old_value, j, temp);
-
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                    new_bit = j;
-                    move = MV_FLIP;
-                }
-            }
-            // reset to what it was before
-            double check = incremental_score(g, fd, old_value);
-            SASSERT(check == score);
-        }
-    }
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-    return new_score;
-}
-
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                        unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
+double sls_engine::find_best_move(
+    ptr_vector<func_decl> & to_evaluate, 
+    double score,
+    unsigned & best_const, 
+    mpz & best_value, 
+    unsigned & new_bit, 
+    move_type & move) 
+{
     mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-    mpz temp2;
-#endif
     unsigned bv_sz;
-#if _INSIST_PERC_
-    double new_score = m_tracker.get_random_uint(16) % 100 < _INSIST_PERC_ ? 0.0 : score;
-#else
     double new_score = score;
-#endif
 
     m_tracker.reset_equal_scores();
 
-//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
     for (unsigned i = 0; i < to_evaluate.size(); i++) {
-//    for (unsigned i = m_tracker.get_random_uint(16) % to_evaluate.size(); i != to_evaluate.size(); i = to_evaluate.size()) {
-//    for (unsigned i = to_evaluate.size(); i-- > 0; ) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
         m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
         // first try to flip every bit
-#if _SKIP_BITS_
-        for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j += (_SKIP_BITS_ + 1)) {
-#else
-//        for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
         for (unsigned j = 0; j < bv_sz; j++) {
-//        for (unsigned j = bv_sz; j-- > 0; ) {
-#endif
             // What would happen if we flipped bit #i ?                
             mk_flip(srt, old_value, j, temp);
 
-            //if (m_tracker.get_random_uint(1))
-            //if ((move != MV_FLIP) || (new_bit > j))
-            //{
-            //if (what_if_new(g, fd, i, temp, new_score, best_const, best_value)) {
-            //    new_bit = j;
-            //    move = MV_FLIP;
-            //}
-            //}
-            //else
-            //{
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
+            if (what_if(fd, i, temp, new_score, best_const, best_value)) {
                 new_bit = j;
                 move = MV_FLIP;
             }
-            //}
         }
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
@@ -590,76 +326,41 @@ double sls_engine::find_best_move(goal_ref const & g, ptr_vector<func_decl> & to
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
-                //if (m_tracker.get_random_uint(1))
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_INC;
             }
             else {
                 // for even values, try -1
                 mk_dec(bv_sz, old_value, temp);
-                //if (m_tracker.get_random_uint(1))
-                if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+                if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
 #endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
-            //if (m_tracker.get_random_uint(1))
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
+            if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
-
-#if _USE_UNARY_MINUS_
-            mk_inc(bv_sz, temp, temp2);
-            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                move = MV_UMIN;
-#endif
-
-#if _USE_MUL2DIV2_
-            // try multiplication by 2
-            mk_mul2(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_MUL2;
-
-#if _USE_MUL3_
-            // try multiplication by 3
-            mk_add(bv_sz, old_value, temp, temp2);
-            if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                move = MV_MUL3;
-#endif
-
-            // try division by 2
-            mk_div2(bv_sz, old_value, temp);
-            if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                move = MV_DIV2;
-#endif
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
         // Andreas: does not hold anymore now that we use top level score caching
         //SASSERT(check == score);
     }
 
     m_mpz_manager.del(old_value);
     m_mpz_manager.del(temp);
-#if _USE_MUL3_
-    m_mpz_manager.del(temp2);
-#endif
-
-    if ((new_score == score) && 1)// (m_tracker.get_random_uint(1)))
-        best_const = -1;
 
     return new_score;
 }
 
 // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
+double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double score,
                         unsigned & best_const, mpz & best_value) {
     mpz old_value, temp, temp2;
     unsigned bv_sz;
     double new_score = score;
 
-//    for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0; i++) {
     for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
@@ -667,22 +368,21 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> &
         m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 2) {
-//            for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
             for (unsigned j = 0; j < bv_sz; j++) {
                 mk_flip(srt, old_value, j, temp);
-                for (unsigned l = 0; l < _VNS_MC_TRIES_ && l < bv_sz / 2; l++)
+                for (unsigned l = 0; l < m_vns_mc && l < bv_sz / 2; l++)
                 {
                     unsigned k = m_tracker.get_random_uint(16) % bv_sz;
                     while (k == j)
                         k = m_tracker.get_random_uint(16) % bv_sz;
                     mk_flip(srt, temp, k, temp2);
-                    what_if(g, fd, i, temp2, new_score, best_const, best_value);
+                    what_if(fd, i, temp2, new_score, best_const, best_value);
                 }
             }
         }
 
         // reset to what it was before
-        double check = incremental_score(g, fd, old_value);
+        double check = incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -692,618 +392,89 @@ double sls_engine::find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> &
     return new_score;
 }
 
-// same as find_best_move but only considers the score of the current expression instead of the overall score
-double sls_engine::find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                            unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-    mpz old_value, temp;
-    unsigned bv_sz;
-    double new_score = m_tracker.get_score(e);
-    // Andreas: tie breaking not implemented yet
-    // double tie_score = top_score(g);
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
-        func_decl * fd = to_evaluate[i];
-        sort * srt = fd->get_range();
-        bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-        m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-        // first try to flip every bit
-        for (unsigned j = 0; j < bv_sz; j++) {
-            // What would happen if we flipped bit #i ?                
-            mk_flip(srt, old_value, j, temp);
-
-            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
-                new_bit = j;
-                move = MV_FLIP;
-            }
-        }
-
-        if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-            if (!m_mpz_manager.is_even(old_value)) {
-                // for odd values, try +1
-                mk_inc(bv_sz, old_value, temp);
-                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_INC;
-            }
-            else {
-                // for even values, try -1
-                mk_dec(bv_sz, old_value, temp);
-                if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                    move = MV_DEC;
-            }
-
-            // try inverting
-            mk_inv(bv_sz, old_value, temp);
-            if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                move = MV_INV;
-        }
-
-        // reset to what it was before
-        m_evaluator.update(fd, old_value);
-    }
-
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-    return new_score;
-}
-
-// first try of intensification ... does not seem to be efficient
-bool sls_engine::handle_plateau(goal_ref const & g)
-{
-    unsigned sz = g->size();
-#if _BFS_
-    unsigned pos = m_stats.m_moves % sz;
-#else
-    unsigned pos = m_tracker.get_random_uint(16) % sz;
-#endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-    if (!e)
-        return 0;
-
-    expr * q = m_tracker.get_unsat_expression(e);
-    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-    for (unsigned i = 0; i < to_evaluate.size(); i++)
-    {
-        m_tracker.get_value(to_evaluate[i]);
-        m_old_values.push_back(&m_tracker.get_value(to_evaluate[i]));
-    }
-    unsigned new_const = (unsigned)-1, new_bit = 0;
-    mpz new_value;
-    move_type move;
-    for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-    {
-        // Andreas: Could be extended to use (best) score but this is computationally more expensive.
-        find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
-
-        if (new_const == static_cast<unsigned>(-1)) {
-            // Andreas: Actually this should never happen.
-            NOT_IMPLEMENTED_YET();
-        }
-        else {
-            m_stats.m_moves++;
-            func_decl * fd = to_evaluate[new_const];
-
-            switch (move) {
-            case MV_FLIP: m_stats.m_flips++; break;
-            case MV_INC: m_stats.m_incs++; break;
-            case MV_DEC: m_stats.m_decs++; break;
-            case MV_INV: m_stats.m_invs++; break;
-            case MV_UMIN: m_stats.m_umins++; break;
-            case MV_MUL2: m_stats.m_mul2s++; break;
-            case MV_MUL3: m_stats.m_mul3s++; break;
-            case MV_DIV2: m_stats.m_div2s++; break;
-            }
-
-            m_evaluator.update(fd, new_value);
-        }
-
-        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-            return 1;
-    }
-
-    for (unsigned i = 0; i < to_evaluate.size(); i++)
-        m_tracker.set_value(to_evaluate[i], *m_old_values[i]);
-
-    m_old_values.reset();
-
-    return 0;
-}
-
-// what_if version needed in the context of 2nd intensification try, combining local and global score
-bool sls_engine::what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                double & best_score, mpz & best_value, unsigned i) {
-
-    double global_score = incremental_score(g, fd, temp);
-    double local_score = m_tracker.get_score(e);
-    double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
-
-    if (new_score >= best_score) {
-        best_score = new_score;
-        m_mpz_manager.set(best_value, temp);
-        return true;
-    }
-
-    return false;
-}
-
-// find_best_move version needed in the context of 2nd intensification try
-double sls_engine::find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-{
-    mpz old_value, temp;
-    double best_score = 0;
-
-    sort * srt = fd->get_range();
-    unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-    m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-    for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
-        mk_flip(srt, old_value, j, temp);
-        what_if(g, e, fd, temp, best_score, best_value, i);
-    }
-
-    m_mpz_manager.del(old_value);
-    m_mpz_manager.del(temp);
-
-    return best_score;
-}
-
-// second try to use intensification ... also not very effective
-bool sls_engine::handle_plateau(goal_ref const & g, double old_score)
-{
-    unsigned sz = g->size();
-#if _BFS_
-    unsigned new_const = m_stats.m_moves % sz;
-#else
-    unsigned new_const = m_tracker.get_random_uint(16) % sz;
-#endif
-    expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-    if (!e)
-        return 0;
-
-    expr * q = m_tracker.get_unsat_expression(e);
-    ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-
-    new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-    func_decl * fd = to_evaluate[new_const];
-
-    mpz new_value;
-    //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-    unsigned new_bit = 0;
-    double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-
-    for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-    {
-        new_score = find_best_move_local(g, q, fd, new_value, i);
-
-        m_stats.m_moves++;
-        m_stats.m_flips++;
-
-        global_score = incremental_score(g, fd, new_value);
-        local_score = m_tracker.get_score(q);
-
-        SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
-
-        if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-            return 1;
-    }
-
-    return 0;
-}
-
 // main search loop
-lbool sls_engine::search(goal_ref const & g) {
+lbool sls_engine::search() {
     lbool res = l_undef;
     double score = 0.0, old_score = 0.0;
-    unsigned new_const = (unsigned)-1, new_bit = 0;
+    unsigned new_const = (unsigned)-1, new_bit;
     mpz new_value;
     move_type move;
-    unsigned plateau_cnt = 0;
 
-    score = rescore(g);
-    unsigned sz = g->size();
-
-    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-    tout << "Score distribution:";
-    for (unsigned i = 0; i < g->size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-    tout << " TOP: " << score << std::endl;);
-
-#if _PERC_STICKY_
-    expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
-#endif
-
-#if _RESTARTS_ == 1
-    while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#elif _RESTARTS_ == 2
-    while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#elif _RESTARTS_ == 3
-    while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#else
-    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {
-#endif
-        //if (m_stats.m_stopwatch.get_current_seconds() > 10.0)
-        //{printf("Got %f fps and size is %d with avg bw %f\n", m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds(), m_tracker.get_formula_size(), m_tracker.get_avg_bw(g)); exit(0);}
+    score = rescore();
+    unsigned sz = m_assertions.size();
 
+    while (check_restart(m_stats.m_moves)) {
         checkpoint();
         m_stats.m_moves++;
+        if (m_stats.m_moves % m_restart_base == 0)
+            m_tracker.ucb_forget(m_assertions);
 
-#if _UCT_FORGET_
-        //if (m_stats.m_moves % sz == 0)
-        if (m_stats.m_moves % _UCT_FORGET_ == 0)
-            m_tracker.uct_forget(g);
-#endif
-
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
-
-#if _FOCUS_
-#if _PERC_STICKY_
-        if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
-            e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
-#else
-        expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);
-#endif
-        if (!e)
-        {
-            res = l_true;
-            goto bailout;
-        }
-        //ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_only(e);
-        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
+        
+        ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
         {
             res = l_true;
             goto bailout;
         }
-#endif
 
-#if _TYPE_RSTEP_
-        if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
+        if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
-#if _TYPE_RSTEP_ == 1
-            m_evaluator.randomize_local(to_evaluate);
-#elif _TYPE_RSTEP_ == 2
             mk_random_move(to_evaluate);
-#endif
-#if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / g->size();
-#else
-            score = top_score(g);
-#endif
+            score = m_tracker.get_top_sum() / sz;
+            continue;
         }
-        continue;
-#endif
 
-#if _WEIGHT_DIST_ == 4
-        m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif       
         old_score = score;
         new_const = (unsigned)-1;
-        move = MV_FLIP;
-        new_bit = 0;
 
-#if _VNS_
-        score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-        score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
+        score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 
-#if _VNS_MC_ > _VNS_REPICK_
-#if _VNS_MC_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
-                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-#endif
-#if _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                {
-                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
-                }
+        if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
+            score = find_best_move_mc(to_evaluate, score, new_const, new_value);
+   
+        /*if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
+        {
+            expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e);
+            if (q)
+            {
+                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move);
             }
-#endif
-#endif
-
-#if _VNS_MC_ < _VNS_REPICK_
-#if _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_) {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                {
-                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
-                }
-            }
-#endif
-#if _VNS_MC_
-        if (new_const == static_cast<unsigned>(-1))
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
-                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-#endif
-#endif
-
-#if (_VNS_MC_ == _VNS_REPICK_) && _VNS_MC_ && _VNS_REPICK_
-        if (new_const == static_cast<unsigned>(-1)) {
-            if (m_tracker.get_random_uint(16) % 100 < _VNS_PERC_)
-                score = find_best_move_mc(g, to_evaluate, score, new_const, new_value);
-            else {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                {
-                    ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
-                    score = find_best_move(g, to_evaluate2, score, new_const, new_value, new_bit, move);
-                }
-            }
-        }        
-#endif
-
+        }*/
 
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
-            plateau_cnt++;
-#if _INTENSIFICATION_
-            handle_plateau(g, score);
-            //handle_plateau(g);
-            //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-            //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-#if _PERC_PLATEAU_MOVES_
-            if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
-                mk_random_move(to_evaluate);
+            if (m_walksat && m_walksat_repick)
+                m_evaluator.randomize_local(m_assertions);
             else
-#endif
-#if _REPICK_ == 1
-                m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _REPICK_ == 2
-            {
-                expr * q = m_tracker.get_new_unsat_assertion(g, e);
-                if (q)
-                    m_evaluator.randomize_local(q);
-                else
-                    m_evaluator.randomize_local(e);
-            }
-#else
-                m_evaluator.randomize_local_n(g, to_evaluate);
-                //m_evaluator.randomize_local(to_evaluate);
-#endif
-#endif
+                m_evaluator.randomize_local(to_evaluate);
 
-#if _CACHE_TOP_SCORE_
-            score = m_tracker.get_top_sum() / g->size();
-#else
-            score = top_score(g);
-#endif
+            score = m_tracker.get_top_sum() / m_assertions.size();
 
-#if _PAWS_
-            for (unsigned i = 0; i < sz; i++)
+            if (m_paws_sp < 1024)
             {
-                expr * q = g->form(i);
-                if (m_tracker.get_random_uint(16) % 100 < _PAWS_)
+                for (unsigned i = 0; i < sz; i++)
                 {
-                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
-                        m_tracker.decrease_weight(q);
-                }
-                else
-                {
-                    if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
-                        m_tracker.increase_weight(q);
+                    expr * q = m_assertions[i];
+                    if (m_tracker.get_random_uint(10) < m_paws_sp)
+                    {
+                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
+                            m_tracker.decrease_weight(q);
+                    }
+                    else
+                    {
+                        if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
+                            m_tracker.increase_weight(q);
+                    }
                 }
             }
-#endif
-
         }
         else {
             func_decl * fd = to_evaluate[new_const];
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
-            score = serious_score(g, fd, new_value);
-#else
-            score = incremental_score(g, fd, new_value);
-#endif
-        }
-    }
-
-bailout:
-    m_mpz_manager.del(new_value);
-
-    return res;
-}
-
-// main search loop
-lbool sls_engine::search_old(goal_ref const & g) {
-    lbool res = l_undef;
-    double score = 0.0, old_score = 0.0;
-    unsigned new_const = (unsigned)-1, new_bit = 0;
-    mpz new_value;
-    move_type move;
-
-    score = rescore(g);
-    TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-    tout << "Score distribution:";
-    for (unsigned i = 0; i < g->size(); i++)
-        tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-    tout << " TOP: " << score << std::endl;);
-
-    unsigned plateau_cnt = 0;
-
-    // Andreas: Why do we only allow so few plateaus?
-#if _RESTARTS_
-    while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
-        //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-    while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {
-#endif
-        do {
-            checkpoint();
-
-#if _WEIGHT_DIST_ == 4
-            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-
-#if _TYPE_RSTEP_
-            if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-            {
-#if _TYPE_RSTEP_ == 1
-                m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _TYPE_RSTEP_ == 2
-                mk_random_move(g);
-#endif
-                score = top_score(g);
-
-                if (score >= 1.0) {
-                    bool all_true = true;
-                    for (unsigned i = 0; i < g->size() && all_true; i++)
-                        if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                            all_true = false;
-                    if (all_true) {
-                        res = l_true; // sat
-                        goto bailout;
-                    }
-                    else
-                        TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                }
-            }
-#endif
-            old_score = score;
-            new_const = (unsigned)-1;
-
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-            if (!to_evaluate.size())
-            {
-                res = l_true;
-                goto bailout;
-            }
-            TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-                tout << to_evaluate[i]->get_name() << std::endl;);
-
-#if _VNS_
-            score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-            score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-            if (new_const == static_cast<unsigned>(-1)) {
-                TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++) {
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
-                });
-
-                TRACE("sls_max", m_tracker.show_model(tout);
-                tout << "Scores: " << std::endl;
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " <<
-                    m_tracker.get_score(g->form(i)) << std::endl;);
-                // Andreas: If new_const == -1, shouldn't score = old_score anyway?
-                score = old_score;
-            }
-            else {
-                // Andreas: Why does randomizing not count as a move? (Now it does.)
-                m_stats.m_moves++;
-                func_decl * fd = to_evaluate[new_const];
-
-                TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
-                switch (move) {
-                case MV_FLIP:
-                    tout << "Flip";
-                    if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
-                    break;
-                case MV_INC:
-                    tout << "+1";
-                    break;
-                case MV_DEC:
-                    tout << "-1";
-                    break;
-                case MV_INV:
-                    tout << "NEG";
-                    break;
-                };
-                tout << ") ; new score = " << std::setprecision(32) << score << std::endl;);
-
-                switch (move) {
-                case MV_FLIP: m_stats.m_flips++; break;
-                case MV_INC: m_stats.m_incs++; break;
-                case MV_DEC: m_stats.m_decs++; break;
-                case MV_INV: m_stats.m_invs++; break;
-                case MV_UMIN: m_stats.m_umins++; break;
-                case MV_MUL2: m_stats.m_mul2s++; break;
-                case MV_MUL3: m_stats.m_mul3s++; break;
-                case MV_DIV2: m_stats.m_div2s++; break;
-                }
-
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
-                score = serious_score(g, fd, new_value);
-#else
-                score = incremental_score(g, fd, new_value);
-#endif
-
-                TRACE("sls", tout << "Score distribution:";
-                for (unsigned i = 0; i < g->size(); i++)
-                    tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                tout << " TOP: " << score << std::endl;);
-            }
-
-            if (score >= 0.99999) {
-                //                    if (score >= 1.0) {
-                // score could theoretically be imprecise.
-                // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
-                bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        all_true = false;
-                if (all_true) {
-                    res = l_true; // sat
-                    goto bailout;
-                }
-                else
-                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-            }
-            /*
-            if (m_stats.m_moves % 100 == 0)
-            {
-            verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-            verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-            }*/
-        } while (score > old_score && res == l_undef);
-
-        // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
-        if (score != old_score) {
-            report_tactic_progress("This should not happen I guess.", plateau_cnt);
-            plateau_cnt = 0;
-        }
-        else {
-            m_stats.m_moves++;
-            plateau_cnt++;
-            //report_tactic_progress("Plateau.", plateau_cnt);
-            // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
-            //if (plateau_cnt < m_plateau_limit) {
-            TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl;);
-#if _INTENSIFICATION_
-            handle_plateau(g, score);
-            //handle_plateau(g);
-#else
-            m_evaluator.randomize_local(g, m_stats.m_moves);
-#endif
-            //mk_random_move(g);
-            score = top_score(g);
-
-            if (score >= 1.0) {
-                bool all_true = true;
-                for (unsigned i = 0; i < g->size() && all_true; i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                        all_true = false;
-                if (all_true) {
-                    res = l_true; // sat
-                    goto bailout;
-                }
-                else
-                    TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-            }
+            score = serious_score(fd, new_value);
         }
     }
 
@@ -1321,80 +492,14 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
 
     m_produce_models = g->models_enabled();
 
-    verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-    verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-    verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
-    verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-    verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-    verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-    verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-    verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-    verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-    verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-    verbose_stream() << "_PAWS_ " << _PAWS_ << std::endl;
-    verbose_stream() << "_PAWS_INIT_ " << _PAWS_INIT_ << std::endl;
-    verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-    verbose_stream() << "_VNS_MC_ " << _VNS_MC_ << std::endl;
-    verbose_stream() << "_VNS_MC_TRIES_ " << _VNS_MC_TRIES_ << std::endl;
-    verbose_stream() << "_VNS_REPICK_ " << _VNS_REPICK_ << std::endl;
-    verbose_stream() << "_VNS_PERC_ " << _VNS_PERC_ << std::endl;
-    verbose_stream() << "_INSIST_PERC_ " << _INSIST_PERC_ << std::endl;
-    verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-    verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-    verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-    verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-    verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
-    verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-    verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-    verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-    verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
-    verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-    verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
-    verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
-    verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-    verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
+    for (unsigned i = 0; i < g->size(); i++)
+        assert_expr(g->form(i));    
+
     verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-    verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-    verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-    verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-    verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-    verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-    verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-    verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-    verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-    verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-    verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
 
-#if _WEIGHT_DIST_ == 4
-    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-    m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-    m_tracker.initialize(g);
-    lbool res = l_undef;
-
-    m_restart_limit = _RESTART_LIMIT_;
-
-    do {
-        checkpoint();
-
-        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-        res = search(g);
-
-        if (res == l_undef)
-        {
-#if _RESTART_INIT_
-            m_tracker.randomize(g);
-#else
-            m_tracker.reset(g);
-#endif
-        }
-    } while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-
-    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+    lbool res = operator()();
 
     if (res == l_true) {
         report_tactic_progress("Number of flips:", m_stats.m_moves);
@@ -1416,33 +521,66 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         mc = 0;
 }
 
-unsigned sls_engine::check_restart(unsigned curr_value)
+lbool sls_engine::operator()() {
+    m_tracker.initialize(m_assertions);
+    lbool res = l_undef;
+
+    do {
+        checkpoint();
+
+        report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
+        res = search();
+
+        if (res == l_undef)
+        {
+            if (m_restart_init)
+                m_tracker.randomize(m_assertions);
+            else
+                m_tracker.reset(m_assertions);
+        }
+    } while (res != l_true && m_stats.m_restarts++ < m_max_restarts);
+
+    verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
+    
+    return res;
+}
+
+/* Andreas: Needed for Armin's restart scheme if we don't want to use loops.
+inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
 {
-    if (curr_value > m_restart_limit)
+    unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
+    unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
+    return pow((double) _RESTART_CONST_ARMIN_, (int) inner_id + 1);
+}    
+*/
+
+inline unsigned sls_engine::check_restart(unsigned curr_value)
+{
+    if (curr_value > m_restart_next)
     {
+        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter.
+        I leave the other versions as comments in case you want to try it again somewhen.
 #if _RESTART_SCHEME_ == 5
-        m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
+        m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
 #elif _RESTART_SCHEME_ == 4
-        m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
+        m_restart_next += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? m_restart_base : (m_restart_base * m_stats.m_restarts + 1);
 #elif _RESTART_SCHEME_ == 3
-        m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+        m_restart_next += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * m_restart_base;
 #elif _RESTART_SCHEME_ == 2
-        m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
+        m_restart_next += get_luby(m_stats.m_restarts + 1) * m_restart_base;
 #elif _RESTART_SCHEME_ == 1
         if (m_stats.m_restarts & 1)
-        //if (m_stats.m_restarts % 3 == 2)
-            m_restart_limit += _RESTART_LIMIT_;
+            m_restart_next += m_restart_base;
         else
-            m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
-            //m_restart_limit += (2 << (m_stats.m_restarts / 3)) * _RESTART_LIMIT_;
+            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
 #else
-        m_restart_limit += _RESTART_LIMIT_;
-#endif
-#if _WEIGHT_TOGGLE_
-        printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-        m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-#endif
+        m_restart_limit += m_restart_base;
+#endif  */
+        if (m_stats.m_restarts & 1)
+            m_restart_next += m_restart_base;
+        else
+            m_restart_next += (2 << (m_stats.m_restarts >> 1)) * m_restart_base;
         return 0;
     }
     return 1;
-}
\ No newline at end of file
+}
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 902c6b7a0..ff0e55f24 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -22,6 +22,7 @@ Notes:
 #include"stopwatch.h"
 #include"lbool.h"
 #include"model_converter.h"
+#include"goal.h"
 
 #include"sls_compilation_settings.h"
 #include"sls_tracker.h"
@@ -35,17 +36,13 @@ public:
         stopwatch       m_stopwatch;
         unsigned        m_full_evals;
         unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
+        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs;
 
         stats() :
             m_restarts(0),
             m_full_evals(0),
             m_incr_evals(0),
             m_moves(0),
-            m_umins(0),
-            m_mul2s(0),
-            m_mul3s(0),
-            m_div2s(0),
             m_flips(0),
             m_incs(0),
             m_decs(0),
@@ -71,14 +68,22 @@ protected:
     bv_util         m_bv_util;
     sls_tracker     m_tracker;
     sls_evaluator   m_evaluator;
+    ptr_vector<expr> m_assertions;
 
-    unsigned		m_restart_limit;
     unsigned        m_max_restarts;
-    unsigned        m_plateau_limit;
+    unsigned        m_walksat;
+    unsigned        m_walksat_repick;
+    unsigned        m_wp;
+    unsigned        m_vns_mc;
+    unsigned        m_vns_repick;
+    unsigned        m_paws_sp;
+    unsigned        m_restart_base;
+    unsigned        m_restart_next;
+    unsigned        m_restart_init;
 
     ptr_vector<mpz> m_old_values;
 
-    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;
+    typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
 public:    
     sls_engine(ast_manager & m, params_ref const & p);
@@ -92,78 +97,46 @@ public:
 
     void updt_params(params_ref const & _p);
 
+    void assert_expr(expr * e) { m_assertions.push_back(e); }
+
     stats const & get_stats(void) { return m_stats; }
     void reset_statistics(void) { m_stats.reset(); }    
 
-    bool full_eval(goal_ref const & g, model & mdl);
-    
+    bool full_eval(model & mdl);
 
     void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result);
-    void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result);
-    void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result);
     void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented);
     void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented);
     void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted);
-    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);    
+    void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped);            
 
-    double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-
-    double find_best_move_lsb(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-
-    double find_best_move_mc(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                          unsigned & best_const, mpz & best_value);
-
-    double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                                unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
-    
-    
-    
-    bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp,
-                 double & best_score, mpz & best_value, unsigned i);
-    
-    double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i);
-    
-
-    lbool search(goal_ref const & g);    
+    lbool search(void);    
 
+    lbool operator()();
     void operator()(goal_ref const & g, model_converter_ref & mc);
 
 protected:
     void checkpoint();
-    lbool search_old(goal_ref const & g);
-    double get_restart_armin(unsigned cnt_restarts);    
 
-    bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
+    bool what_if(func_decl * fd, const unsigned & fd_inx, const mpz & temp,
                  double & best_score, unsigned & best_const, mpz & best_value);
 
-    bool what_if_new(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                 double & best_score, unsigned & best_const, mpz & best_value);
-    double incremental_score_prune_new(goal_ref const & g, func_decl * fd, const mpz & new_value);
+    double top_score();
+    double rescore();
+    double serious_score(func_decl * fd, const mpz & new_value);
+    double incremental_score(func_decl * fd, const mpz & new_value);
 
-    bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp,
-                       double & best_score, unsigned & best_const, mpz & best_value);
+    double incremental_score_prune(func_decl * fd, const mpz & new_value);
+    double find_best_move(ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
 
-    double top_score(goal_ref const & g);
-    double rescore(goal_ref const & g);
-    double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
-    double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value);
-
-#if _EARLY_PRUNE_
-    double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value);
-#endif
-
-    double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move);
+    double find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double score,
+                          unsigned & best_const, mpz & best_value);
 
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
-    void mk_random_move(goal_ref const & g);
-
-    bool handle_plateau(goal_ref const & g);
-    bool handle_plateau(goal_ref const & g, double old_score);
 
+    //inline double get_restart_armin(unsigned cnt_restarts);    
     inline unsigned check_restart(unsigned curr_value);
 };
 
-#endif
\ No newline at end of file
+#endif
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 78f2cb79a..37bfa5a2d 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -81,11 +81,7 @@ public:
             case OP_AND: {
                 m_mpz_manager.set(result, m_one);
                 for (unsigned i = 0; i < n_args; i++)
-#if _DIRTY_UP_
-                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) && !m_tracker.is_top_expr(args[i]))  {
-#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result))  {
-#endif
                         m_mpz_manager.set(result, m_zero);
                         break;
                     }
@@ -93,11 +89,7 @@ public:
             }
             case OP_OR: {
                 for (unsigned i = 0; i < n_args; i++)
-#if _DIRTY_UP_
-                    if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result) || m_tracker.is_top_expr(args[i]))  {
-#else
                     if (m_mpz_manager.neq(m_tracker.get_value(args[i]), result)) {
-#endif
                         m_mpz_manager.set(result, m_one);
                         break;
                     }
@@ -105,16 +97,9 @@ public:
             }
             case OP_NOT: {
                 SASSERT(n_args == 1);
-#if _DIRTY_UP_
-                if (m_tracker.is_top_expr(args[0]))
-                    m_mpz_manager.set(result, m_zero);
-                else
-                    m_mpz_manager.set(result, (m_mpz_manager.is_zero(m_tracker.get_value(args[0]))) ? m_one : m_zero);
-#else
                 const mpz & child = m_tracker.get_value(args[0]);
                 SASSERT(m_mpz_manager.is_one(child) || m_mpz_manager.is_zero(child));                
                 m_mpz_manager.set(result, (m_mpz_manager.is_zero(child)) ? m_one : m_zero);
-#endif
                 break;
             }
             case OP_EQ: {
@@ -545,9 +530,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
         double new_score;
-#endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
@@ -559,8 +542,7 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 
-#if _REAL_RS_ || _REAL_PBFS_
-                //if (!m_tracker.has_uplinks(cur))
+#if _REAL_RS_
                 if (m_tracker.is_top_expr(cur))
                 {
                     if (m_mpz_manager.eq(new_value,m_one))
@@ -570,25 +552,12 @@ public:
                 }
 #endif
 
+                new_score = m_tracker.score(cur);
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #if _EARLY_PRUNE_
-                new_score = m_tracker.score(cur);
-#if _CACHE_TOP_SCORE_
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
-                m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
-#else
-#if _CACHE_TOP_SCORE_
-                new_score = m_tracker.score(cur);
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                m_tracker.set_score(cur, new_score);
-#else
-                m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
 #endif            
 
                 if (m_tracker.has_uplinks(cur)) {
@@ -617,9 +586,7 @@ public:
         expr_fast_mark1 visited;
         mpz new_value;
 
-#if _EARLY_PRUNE_ || _CACHE_TOP_SCORE_
         double new_score;
-#endif
 
         SASSERT(cur_depth < m_traversal_stack.size());
         while (cur_depth != static_cast<unsigned>(-1)) {
@@ -630,25 +597,12 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
+                new_score = m_tracker.score(cur);
+                if (m_tracker.is_top_expr(cur))
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
+                m_tracker.set_score(cur, new_score);
 #if _EARLY_PRUNE_
-                new_score = m_tracker.score(cur);
-#if _CACHE_TOP_SCORE_
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
-                m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
-#else
-#if _CACHE_TOP_SCORE_
-                new_score = m_tracker.score(cur);
-                //if (!m_tracker.has_uplinks(cur))
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                m_tracker.set_score(cur, new_score);
-#else
-                m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
 #endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -684,11 +638,7 @@ public:
             m_traversal_stack[cur_depth].push_back(ep);
             if (cur_depth > max_depth) max_depth = cur_depth;
         }
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         run_serious_update(max_depth);
-#else
-        run_update(max_depth);
-#endif
     }
 
     void update(func_decl * fd, const mpz & new_value) {
@@ -713,7 +663,6 @@ public:
         run_serious_update(cur_depth);
     }
 
-#if _EARLY_PRUNE_
     unsigned run_update_bool_prune(unsigned cur_depth) {
         expr_fast_mark1 visited;
 
@@ -727,19 +676,15 @@ public:
             expr * cur = cur_depth_exprs[i];
 
             new_score = m_tracker.score(cur); 
-#if _CACHE_TOP_SCORE_
-            //if (!m_tracker.has_uplinks(cur))
             if (m_tracker.is_top_expr(cur))
                 m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-#endif
+
             prune_score = m_tracker.get_score_prune(cur);
             m_tracker.set_score(cur, new_score);
 
             if ((new_score > prune_score) && (m_tracker.has_pos_occ(cur)))
-            //if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
                 pot_benefits = 1;
             if ((new_score <= prune_score) && (m_tracker.has_neg_occ(cur)))
-            //if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
                 pot_benefits = 1;
 
             if (m_tracker.has_uplinks(cur)) {
@@ -754,9 +699,6 @@ public:
                     }
                 }
             }
-            else
-            {
-            }
         }
 
         cur_depth_exprs.reset();
@@ -770,15 +712,11 @@ public:
                 for (unsigned i = 0; i < cur_size; i++) {
                     expr * cur = cur_depth_exprs[i];
 
-#if _CACHE_TOP_SCORE_
                     new_score = m_tracker.score(cur); 
-                    //if (!m_tracker.has_uplinks(cur))
                     if (m_tracker.is_top_expr(cur))
                         m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     m_tracker.set_score(cur, new_score);
-#else
-                    m_tracker.set_score(cur, m_tracker.score(cur));
-#endif
+
                     if (m_tracker.has_uplinks(cur)) {
                         ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                         for (unsigned j = 0; j < ups.size(); j++) {
@@ -859,161 +797,18 @@ public:
         }
         return run_update_bool_prune(cur_depth);
     }
-#endif
-
-    unsigned run_update_bool_prune_new(unsigned cur_depth) {
-        expr_fast_mark1 visited;
-
-        double prune_score, new_score;
-        unsigned pot_benefits = 0;
-        SASSERT(cur_depth < m_traversal_stack_bool.size());
- 
-        ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-
-        for (unsigned i = 0; i < cur_depth_exprs.size(); i++) {
-            expr * cur = cur_depth_exprs[i];
-
-            new_score = m_tracker.score(cur); 
-            //if (!m_tracker.has_uplinks(cur))
-            if (m_tracker.is_top_expr(cur))
-                m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-            prune_score = m_tracker.get_score_prune(cur);
-            m_tracker.set_score(cur, new_score);
-
-            if ((new_score >= prune_score) && (m_tracker.has_pos_occ(cur)))
-                pot_benefits = 1;
-            if ((new_score < prune_score) && (m_tracker.has_neg_occ(cur)))
-                pot_benefits = 1;
-
-            if (m_tracker.has_uplinks(cur)) {
-                ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                for (unsigned j = 0; j < ups.size(); j++) {
-                    expr * next = ups[j];
-                    unsigned next_d = m_tracker.get_distance(next);
-                    SASSERT(next_d < cur_depth);
-                    if (!visited.is_marked(next)) {
-                        m_traversal_stack_bool[next_d].push_back(next);
-                        visited.mark(next);
-                    }
-                }
-            }
-            else
-            {
-            }
-        }
-
-        cur_depth_exprs.reset();
-        cur_depth--;
- 
-        while (cur_depth != static_cast<unsigned>(-1)) {
-            ptr_vector<expr> & cur_depth_exprs = m_traversal_stack_bool[cur_depth];
-            if (pot_benefits)
-            {
-                unsigned cur_size = cur_depth_exprs.size();
-                for (unsigned i = 0; i < cur_size; i++) {
-                    expr * cur = cur_depth_exprs[i];
-
-                    new_score = m_tracker.score(cur); 
-                    //if (!m_tracker.has_uplinks(cur))
-                    if (m_tracker.is_top_expr(cur))
-                        m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
-                    m_tracker.set_score(cur, new_score);
-                    if (m_tracker.has_uplinks(cur)) {
-                        ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
-                        for (unsigned j = 0; j < ups.size(); j++) {
-                            expr * next = ups[j];
-                            unsigned next_d = m_tracker.get_distance(next);
-                            SASSERT(next_d < cur_depth);
-                            if (!visited.is_marked(next)) {
-                                m_traversal_stack_bool[next_d].push_back(next);
-                                visited.mark(next);
-                            }
-                        }
-                    }
-                }
-            }
-            cur_depth_exprs.reset();
-            cur_depth--;
-        }
-
-        return pot_benefits;
-    }
-
-    unsigned update_prune_new(func_decl * fd, const mpz & new_value) {
-        m_tracker.set_value(fd, new_value);
-        expr * ep = m_tracker.get_entry_point(fd);
-        unsigned cur_depth = m_tracker.get_distance(ep);
-
-        if (m_traversal_stack_bool.size() <= cur_depth)
-            m_traversal_stack_bool.resize(cur_depth+1);
-        if (m_traversal_stack.size() <= cur_depth) 
-                m_traversal_stack.resize(cur_depth+1);
-
-        if (m_manager.is_bool(ep))
-            m_traversal_stack_bool[cur_depth].push_back(ep);
-        else
-        {
-            m_traversal_stack[cur_depth].push_back(ep);
-            run_update_prune(cur_depth);
-        }
-        return run_update_bool_prune_new(cur_depth);
-    }
 
     void randomize_local(ptr_vector<func_decl> & unsat_constants) {
-        // Randomize _all_ candidates:
-
-        //// bool did_something = false;
-        //for (unsigned i = 0; i < unsat_constants.size(); i++) {
-        //    func_decl * fd = unsat_constants[i];
-        //    mpz temp = m_tracker.get_random(fd->get_range());
-        //    // if (m_mpz_manager.neq(temp, m_tracker.get_value(fd))) {
-        //    //     did_something = true;
-        //    // }
-        //    update(fd, temp);
-        //    m_mpz_manager.del(temp);
-        //}
-
         // Randomize _one_ candidate:
         unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
         func_decl * fd = unsat_constants[r];
-#if _PERC_CHANGE_
-        sort * srt = fd->get_range();
-        mpz temp;
-
-        if (m_manager.is_bool(srt))
-            m_mpz_manager.set(temp, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-        else
-        {
-            mpz temp2, mask;
-            unsigned bv_sz = m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(temp, m_tracker.get_value(fd));
-
-            for (unsigned bit = 0; bit < bv_sz; bit++)
-                if (m_tracker.get_random_uint(16) % 100 < _PERC_CHANGE_)
-                {
-                    m_mpz_manager.set(mask, m_powers(bit));
-                    m_mpz_manager.bitwise_xor(temp, mask, temp2);
-                    m_mpz_manager.set(temp, temp2);
-                }
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(temp2);
-        }
-#else
         mpz temp = m_tracker.get_random(fd->get_range());
-#endif
 
-#if _REAL_RS_ || _REAL_PBFS_ || _PAWS_
         serious_update(fd, temp);
-#else
-        update(fd, temp);
-#endif
+
         m_mpz_manager.del(temp);
 
-        TRACE("sls", /*tout << "Randomization candidates: ";
-                        for (unsigned i = 0; i < unsat_constants.size(); i++)
-                            tout << unsat_constants[i]->get_name() << ", ";
-                        tout << std::endl;*/
-                        tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
+        TRACE("sls",    tout << "Randomization candidate: " << unsat_constants[r]->get_name() << std::endl;
                         tout << "Locally randomized model: " << std::endl; 
                         m_tracker.show_model(tout); );
 
@@ -1023,36 +818,9 @@ public:
         randomize_local(m_tracker.get_constants(e));
     } 
 
-    void randomize_local(goal_ref const & g, unsigned int flip) {
-        randomize_local(m_tracker.get_unsat_constants(g, flip));
+    void randomize_local(ptr_vector<expr> const & as) {
+        randomize_local(m_tracker.get_unsat_constants(as));
     } 
-
-    void randomize_local_n(goal_ref const & g, ptr_vector<func_decl> & unsat_constants) {
-        unsigned r = m_tracker.get_random_uint(16) % unsat_constants.size();
-        func_decl * fd = unsat_constants[r];
-        sort * srt = fd->get_range();
-        unsigned bv_sz = m_manager.is_bool(srt) ? 1 : m_bv_util.get_bv_size(srt); 
-        mpz max_val = m_tracker.get_random(srt);
-        update(fd, max_val);
-        double max_score = m_tracker.get_top_sum() / g->size();
-        mpz temp_val;
-        double temp_score;
-        for (unsigned i = 1; i < 2; i++)
-        //for (unsigned i = 1; i < bv_sz; i++)
-        {
-            m_mpz_manager.set(temp_val, m_tracker.get_random(srt));
-            update(fd, temp_val);
-            temp_score = m_tracker.get_top_sum() / g->size();
-            if (temp_score > max_score)
-            {
-                m_mpz_manager.set(max_val, temp_val);
-                max_score = temp_score;
-            }
-        }
-        update(fd, max_val);
-        m_mpz_manager.del(temp_val);
-        m_mpz_manager.del(max_val);
-    }
 };
 
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 0b6b01e7c..6e1102dd2 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -1507,16 +1507,12 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
                              using_params(mk_simplify_tactic(m), simp2_p)),
                         using_params(mk_simplify_tactic(m), hoist_p),
                         mk_max_bv_sharing_tactic(m),
-                        // Andreas: It would be cool to get rid of shared top level assertions but which simplification is doing this?
-                        //mk_ctx_simplify_tactic(m, ctx_p),
-                        // Andreas: This one at least eliminates top level duplicates ... but has very bad effects on performance!
-                        //mk_simplify_tactic(m),
                         mk_nnf_tactic(m, p));
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
     tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
-//    tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
+    //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 87c90f1f8..65011dc8d 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,7 +20,9 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
-#include"goal.h"
+#include"for_each_expr.h"
+#include"ast_smt2_pp.h"
+#include"bv_decl_plugin.h"
 #include"model.h"
 
 #include"sls_compilation_settings.h"
@@ -37,11 +39,7 @@ class sls_tracker {
     mpz                   m_zero, m_one, m_two;
         
     struct value_score { 
-#if _EARLY_PRUNE_
         value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
-#else
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1) { };
-#endif
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;
@@ -78,24 +76,22 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
-#if _UCT_
+
+    unsigned              m_walksat;
+    unsigned              m_ucb;
+    double                m_ucb_constant;
+    unsigned              m_ucb_init;
+    double                m_ucb_forget;
     unsigned              m_touched;
-#endif
-#if _REAL_RS_ || _REAL_PBFS_
+    double                m_scale_unsat;
+    unsigned              m_paws_init;
+#if _REAL_RS_
     ptr_vector<expr>	  m_unsat_expr;
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
 #endif
-#if _PAWS_
     obj_map<expr, unsigned> m_weights;
-    //obj_map<expr, double> m_weights;
-#endif
-#if _CACHE_TOP_SCORE_
     double				  m_top_sum;
-#endif
-#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
-    double				  m_weight_dist_factor;
-#endif
     unsigned              m_equal_scores;
 
 public:    
@@ -116,6 +112,17 @@ public:
         m_mpz_manager.del(m_two);            
     }
 
+    void updt_params(params_ref const & _p) {
+        sls_params p(_p);
+        m_walksat = p.walksat();
+        m_ucb = p.walksat_ucb();
+        m_ucb_constant = p.walksat_ucb_constant();
+        m_ucb_init = p.walksat_ucb_init();
+        m_ucb_forget = p.walksat_ucb_forget();
+        m_scale_unsat = p.scale_unsat();
+        m_paws_init = p.paws_init();
+    }
+
     unsigned get_formula_size() {
         return m_scores.size();
     }
@@ -141,12 +148,6 @@ public:
         return sum / count;   
     }
 
-#if _WEIGHT_DIST_ == 4 || _WEIGHT_TOGGLE_
-    inline void set_weight_dist_factor(double val) {
-        m_weight_dist_factor = val;
-    }
-#endif
-
     void reset_equal_scores() {
         m_equal_scores = 1;
     }
@@ -155,13 +156,8 @@ public:
         return ++m_equal_scores;
     }
 
-#if _CACHE_TOP_SCORE_
     inline void adapt_top_sum(expr * e, double add, double sub) {
-#if _PAWS_
         m_top_sum += m_weights.find(e) * (add - sub);
-#else
-        m_top_sum += add - sub;
-#endif
     }
 
     inline void set_top_sum(double new_score) {
@@ -171,7 +167,6 @@ public:
     inline double get_top_sum() {
         return m_top_sum;
     }
-#endif
 
     inline void set_value(expr * n, const mpz & r) {
         SASSERT(m_scores.contains(n));
@@ -217,7 +212,6 @@ public:
         return get_score(ep);
     }
 
-#if _EARLY_PRUNE_
     inline void set_score_prune(expr * n, double score) {
         SASSERT(m_scores.contains(n));
         m_scores.find(n).score_prune = score;
@@ -237,7 +231,6 @@ public:
         SASSERT(m_scores.contains(n));
         return m_scores.find(n).has_neg_occ;
     }
-#endif
 
     inline unsigned get_distance(expr * n) {
         SASSERT(m_scores.contains(n));
@@ -271,7 +264,7 @@ public:
         return m_uplinks.find(n);
     }
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
     void debug_real(goal_ref const & g, unsigned flip)
     {
         unsigned count = 0;
@@ -318,21 +311,22 @@ public:
     }
 #endif
 
-#if _UCT_
-    void uct_forget(goal_ref const & g) {
-        expr * e;
-        unsigned touched_old, touched_new;
-
-        for (unsigned i = 0; i < g->size(); i++)
+    inline void ucb_forget(ptr_vector<expr> & as) {
+        if (m_ucb_forget < 1.0)
         {
-            e = g->form(i);
-            touched_old = m_scores.find(e).touched;
-            touched_new = (unsigned)((touched_old - 1) * _UCT_FORGET_FACTOR_ + 1);
-            m_scores.find(e).touched = touched_new;
-            m_touched += touched_new - touched_old;
+            expr * e;
+            unsigned touched_old, touched_new;
+
+            for (unsigned i = 0; i < as.size(); i++)
+            {
+                e = as[i];
+                touched_old = m_scores.find(e).touched;
+                touched_new = (unsigned)((touched_old - 1) * m_ucb_forget + 1);
+                m_scores.find(e).touched = touched_new;
+                m_touched += touched_new - touched_old;
+            }
         }
     }
-#endif
 
     void initialize(app * n) {
         // Build score table
@@ -409,12 +403,12 @@ public:
         }
     };
 
-    void calculate_expr_distances(goal_ref const & g) {
+    void calculate_expr_distances(ptr_vector<expr> const & as) {
         // precondition: m_scores is set up.
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         ptr_vector<app> stack;
         for (unsigned i = 0; i < sz; i++)
-            stack.push_back(to_app(g->form(i)));
+            stack.push_back(to_app(as[i]));
         while (!stack.empty()) {
             app * cur = stack.back();
             stack.pop_back();
@@ -462,31 +456,24 @@ public:
         quick_for_each_expr(ffd_proc, visited, e);
     }
 
-    void initialize(goal_ref const & g) {
+    void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
         expr_mark visited;
-        unsigned sz = g->size();
+        unsigned sz = as.size();
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
             else
                 printf("this is already in ...\n");
-            // Andreas: Maybe not fully correct.
-#if _FOCUS_ == 2
-            initialize_recursive(proc, visited, e);
-#endif
             for_each_expr(proc, visited, e);
         }
 
         visited.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
+            expr * e = as[i];
             // Andreas: Maybe not fully correct.
-#if _FOCUS_ == 2 || _INTENSIFICATION_
-            initialize_recursive(e);
-#endif
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -494,11 +481,11 @@ public:
             quick_for_each_expr(ffd_proc, visited, e);
         }
 
-        calculate_expr_distances(g);
+        calculate_expr_distances(as);
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
         m_list_false = new expr*[sz];
         //for (unsigned i = 0; i < sz; i++)
         //{
@@ -507,50 +494,38 @@ public:
         //}
 #endif
 
-#if _PAWS_
         for (unsigned i = 0; i < sz; i++)
         {
-            expr * e = g->form(i);
+            expr * e = as[i];
         	if (!m_weights.contains(e))
-        		m_weights.insert(e, _PAWS_INIT_);
+        		m_weights.insert(e, m_paws_init);
         }
-#endif
 
 #if _EARLY_PRUNE_
         for (unsigned i = 0; i < sz; i++)
-            setup_occs(g->form(i));
+            setup_occs(as[i]);
 #endif
 
-#if _UCT_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-#endif
+        m_touched = m_ucb_init ? as.size() : 1;
     }
 
-#if _PAWS_
     void increase_weight(expr * e)
     {
-        //printf("Increasing %d to", m_weights.find(e));
         m_weights.find(e)++;
-        //m_weights.find(e) *= 1.1;
-        //printf(" %d\n", m_weights.find(e));
     }
 
     void decrease_weight(expr * e)
     {
         unsigned old_weight = m_weights.find(e);
-        m_weights.find(e) = old_weight > _PAWS_INIT_ ? old_weight - 1 : _PAWS_INIT_;
-        //m_weights.find(e) = old_weight > 1.1 ? old_weight / 1.1 : 1;
-        //printf("Decreasing %d to %d\n", old_weight, m_weights.find(e));
+        m_weights.find(e) = old_weight > m_paws_init ? old_weight - 1 : m_paws_init;
     }
 
     unsigned get_weight(expr * e)
-    //double get_weight(expr * e)
     {
         return m_weights.find(e);
     }
-#endif
 
-#if _REAL_RS_ || _REAL_PBFS_
+#if _REAL_RS_
     void make_assertion(expr * e)
     {
         if (m_where_false.contains(e))
@@ -683,7 +658,7 @@ public:
             NOT_IMPLEMENTED_YET(); // This only works for bit-vectors for now.
     }    
 
-    void randomize(goal_ref const & g) {
+    void randomize(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -695,15 +670,9 @@ public:
         }
 
         TRACE("sls", tout << "Randomized model:" << std::endl; show_model(tout); );
-
-#if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
-#endif
     }              
 
-    void reset(goal_ref const & g) {
+    void reset(ptr_vector<expr> const & as) {
         TRACE("sls", tout << "Abandoned model:" << std::endl; show_model(tout); );
 
         for (entry_point_type::iterator it = m_entry_points.begin(); it != m_entry_points.end(); it++) {
@@ -711,15 +680,8 @@ public:
             set_value(it->m_value, temp);
             m_mpz_manager.del(temp);
         }
-
-#if _UCT_RESET_
-        m_touched = _UCT_INIT_ ? g->size() : 1;
-        for (unsigned i = 0; i < g->size(); i++)
-            m_scores.find(g->form(i)).touched = 1;
-#endif
     }              
 
-#if _EARLY_PRUNE_
     void setup_occs(expr * n, bool negated = false) {
         if (m_manager.is_bool(n))
         {
@@ -752,7 +714,6 @@ public:
         else
             NOT_IMPLEMENTED_YET();
     }
-#endif
 
     double score_bool(expr * n, bool negated = false) {
         TRACE("sls_score", tout << ((negated)?"NEG ":"") << "BOOL: " << mk_ismt2_pp(n, m_manager) << std::endl; );
@@ -770,57 +731,29 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            // Andreas: Seems to have no effect. Probably it does not even occur.
-#if _SCORE_AND_AVG_
+            /* Andreas: Seems to have no effect. But maybe you want to try it again at some point.
             double sum = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++)
-#if _DIRTY_UP_
-                sum += is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
                 sum += get_score(args[i]);
-#endif
-            res = sum / (double) a->get_num_args();
-#else
+            res = sum / (double) a->get_num_args(); */
             double min = 1.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
-#if _DIRTY_UP_
-                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
                 double cur = get_score(args[i]);
-#endif
                 if (cur < min) min = cur;
             }
             res = min;
-#endif
         }
         else if (m_manager.is_or(n)) {
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
             // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
-#if _SCORE_OR_MUL_
-            double inv = 1.0;
-            for (unsigned i = 0; i < a->get_num_args(); i++) {
-#if _DIRTY_UP_
-                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
-                double cur = get_score(args[i]);
-#endif
-                inv *= (1.0 - get_score(args[i]));
-            }
-            res = 1.0 - inv;
-#else
             double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
-#if _DIRTY_UP_
-                double cur = is_top_expr(args[i]) ? 1.0 : get_score(args[i]);
-#else
                 double cur = get_score(args[i]);
-#endif
                 if (cur > max) max = cur;
             }
             res = max;
-#endif
         }
         else if (m_manager.is_ite(n)) {
             SASSERT(!negated);
@@ -855,24 +788,14 @@ public:
                 m_mpz_manager.bitwise_xor(v0, v1, diff);
                 unsigned hamming_distance = 0;
                 unsigned bv_sz = m_bv_util.get_bv_size(arg0);
-                #if 1 // unweighted hamming distance
+                // unweighted hamming distance
                 while (!m_mpz_manager.is_zero(diff)) {
-                    //m_mpz_manager.set(diff_m1, diff);
-                    //m_mpz_manager.dec(diff_m1);
-                    //m_mpz_manager.bitwise_and(diff, diff_m1, diff);
-                    //hamming_distance++;
                     if (!m_mpz_manager.is_even(diff)) {
                         hamming_distance++;
                     }
                     m_mpz_manager.machine_div(diff, m_two, diff);
                 }
                 res = 1.0 - (hamming_distance / (double) bv_sz);
-                #else                    
-                rational r(diff);
-                r /= m_powers(bv_sz);
-                double dbl = r.get_double();
-                res = (dbl < 0.0) ? 1.0 : (dbl > 1.0) ? 0.0 : 1.0 - dbl;
-                #endif
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << " ; HD = " << hamming_distance << 
                                         " ; SZ = " << bv_sz << std::endl; );                    
@@ -891,205 +814,36 @@ public:
 
             if (negated) {
                 if (m_mpz_manager.gt(x, y))
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(x, y, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-/*                  mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_gt = 0;
-                    unsigned curr_gt = 0;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 1;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 0;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
-                    m_mpz_manager.del(x_copy);
-                    m_mpz_manager.del(y_copy);*/
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);                            
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));                            
-                    double dbl = 1.0 - n.get_double();
+                    double dbl = n.get_double();
                     // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
-                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
             }
             else {
                 if (m_mpz_manager.le(x, y))                        
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(y, x, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-/*                  mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_le = 1;
-                    unsigned curr_le = 1;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 0;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 1;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);*/
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
                     rational n(diff);
                     n /= rational(m_powers(bv_sz));
-                    double dbl = 1.0 - n.get_double();
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    double dbl = n.get_double();
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
             }
             TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                     m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
         }
-/*        else if (m_bv_util.is_bv_sle(n)) { // x <= y
-            app * a = to_app(n);
-            SASSERT(a->get_num_args() == 2);
-            const mpz & x = get_value(a->get_arg(0));
-            const mpz & y = get_value(a->get_arg(1));
-            int bv_sz = m_bv_util.get_bv_size(a->get_decl()->get_domain()[0]);
-
-            mpz x_unsigned;
-            mpz y_unsigned;
-            const mpz & p = m_powers(bv_sz);
-            const mpz & p_half = m_powers(bv_sz-1);
-            if (x >= p_half) { m_mpz_manager.sub(x, p, x_unsigned); } 
-            if (y >= p_half) { m_mpz_manager.sub(y, p, y_unsigned); }                 
-
-            if (negated) {
-                if (x_unsigned > y_unsigned)
-                    res = 1.0; 
-                else {
-                    mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_gt = 0;
-                    unsigned curr_gt = 0;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 1;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_gt = curr_gt;
-                            curr_gt = 0;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_gt) / (double)(bv_sz + 2);
-                    m_mpz_manager.del(x_copy);
-                    m_mpz_manager.del(y_copy);
-                }
-            }
-            else {
-                if (x_unsigned <= y_unsigned)                        
-                    res = 1.0; 
-                else {
-                    mpz x_copy, y_copy;
-                    m_mpz_manager.set(x_copy, x);
-                    m_mpz_manager.set(y_copy, y);
-                    unsigned lower_le = 1;
-                    unsigned curr_le = 1;
-                    int last_pos = -1;
-                    for (int i = 0; i < bv_sz; i++)
-                    {
-                        if (m_mpz_manager.is_odd(x_copy) && m_mpz_manager.is_even(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 0;
-                            last_pos = i;
-                        }
-                        else if (m_mpz_manager.is_even(x_copy) && m_mpz_manager.is_odd(y_copy))
-                        {
-                            lower_le = curr_le;
-                            curr_le = 1;
-                            last_pos = i;
-                        }
- 
-                        m_mpz_manager.machine_div(x_copy, m_two, x_copy);
-                        m_mpz_manager.machine_div(y_copy, m_two, y_copy);
-                    }
-
-                    res = (double)(bv_sz - last_pos - 1 + 2 * lower_le) / (double)(bv_sz + 2);
-                }
-            }
-            TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
-                                    m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
-
-            m_mpz_manager.del(x_unsigned);
-            m_mpz_manager.del(y_unsigned);
-        }*/
-      else if (m_bv_util.is_bv_sle(n)) { // x <= y
+        else if (m_bv_util.is_bv_sle(n)) { // x <= y
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 2);
             mpz x; m_mpz_manager.set(x, get_value(a->get_arg(0)));
@@ -1102,61 +856,32 @@ public:
 
             if (negated) {
                 if (x > y)
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(x, y, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(y, x, diff);
                     m_mpz_manager.inc(diff);
                     rational n(diff);
                     n /= p;
-                    double dbl = 1.0 - n.get_double();
-                    //res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    double dbl = n.get_double();
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
             }
             else {
                 if (x <= y)
-                {
-                    /*mpz diff;
-                    m_mpz_manager.sub(y, x, diff);
-                    m_mpz_manager.inc(diff);                            
-                    rational n(diff);
-                    n /= rational(m_powers(bv_sz));                            
-                    double dbl = n.get_double();
-                    // In extreme cases, n is 0.9999 but to_double returns something > 1.0
-                    m_mpz_manager.del(diff);
-                    res = 1.0 + 0.5 * dbl;*/
                     res = 1.0; 
-                }
                 else {
-                    //res = (bv_sz - 1.0) / bv_sz;
-#if 1
                     mpz diff;
                     m_mpz_manager.sub(x, y, diff);
                     SASSERT(!m_mpz_manager.is_neg(diff));
                     rational n(diff);
                     n /= p;
-                    double dbl = 1.0 - n.get_double();
-                    res = (dbl > 1.0) ? 1.0 : (dbl < 0.0) ? 0.0 : dbl;
+                    double dbl = n.get_double();
+                    res = (dbl > 1.0) ? 0.0 : (dbl < 0.0) ? 1.0 : 1.0 - dbl;
                     m_mpz_manager.del(diff);
-#endif
                 }
                 TRACE("sls_score", tout << "x = " << m_mpz_manager.to_string(x) << " ; y = " << 
                                         m_mpz_manager.to_string(y) << " ; SZ = " << bv_sz << std::endl; );
@@ -1171,11 +896,7 @@ public:
             expr * child = a->get_arg(0);
             if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
                 NOT_IMPLEMENTED_YET();
-#if _DIRTY_UP_
-            res = is_top_expr(child) ? 0.0 : score_bool(child, true);
-#else
             res = score_bool(child, true);
-#endif
         }
         else if (m_manager.is_distinct(n)) {
             app * a = to_app(n);
@@ -1199,25 +920,11 @@ public:
 
         SASSERT(res >= 0.0 && res <= 1.0);
 
-#if _WEIGHT_DIST_
         app * a = to_app(n);
         family_id afid = a->get_family_id();
 
         if (afid == m_bv_util.get_family_id())
-#endif
-#if _WEIGHT_DIST_ == 1
-#if _WEIGHT_TOGGLE_
-        if (res < 1.0) res *= m_weight_dist_factor;
-#else
-        if (res < 1.0) res *= _WEIGHT_DIST_FACTOR_;
-#endif
-#elif _WEIGHT_DIST_ == 2
-        res *= res;
-#elif _WEIGHT_DIST_ == 3
-        if (res < 1.0) res = 0.0;
-#elif _WEIGHT_DIST_ == 4
-        if (res < 1.0) res *= m_weight_dist_factor;
-#endif
+            if (res < 1.0) res *= m_scale_unsat;
 
         TRACE("sls_score", tout << "SCORE = " << res << std::endl; );
         return res;
@@ -1268,33 +975,6 @@ public:
             NOT_IMPLEMENTED_YET();
     }    
 
-    expr * get_unsat_expression(expr * e) {
-        if (m_manager.is_bool(e)) {
-            if (m_manager.is_and(e) || m_manager.is_or(e)) {
-                app * a = to_app(e);
-                expr * const * args = a->get_args();
-                // Andreas: might be used for guided branching
-                //for (unsigned i = 0; i < a->get_num_args(); i++) {
-                    //double cur = get_score(args[i]);
-                //}
-                // Andreas: A random number is better here since reusing flip will cause patterns.
-                unsigned int sz = a->get_num_args();
-                unsigned int pos = get_random_uint(16) % sz;
-                for (unsigned int i = pos; i < sz; i++) {
-                    expr * q = args[i];
-                    if (m_mpz_manager.neq(get_value(q), m_one))
-                        return get_unsat_expression(q);
-                }
-                for (unsigned int i = 0; i < pos; i++) {
-                    expr * q = args[i];
-                    if (m_mpz_manager.neq(get_value(q), m_one))
-                        return get_unsat_expression(q);
-                }
-            }
-        }
-        return e;
-    }
-
     ptr_vector<func_decl> & get_constants(expr * e) {
         ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
         unsigned sz = this_decls.size();
@@ -1306,13 +986,17 @@ public:
         return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & get_unsat_constants_gsat(goal_ref const & g, unsigned sz) {
-        if (sz == 1)
-            return get_constants();
+    ptr_vector<func_decl> & get_unsat_constants_gsat(ptr_vector<expr> const & as) {
+        unsigned sz = as.size();
+        if (sz == 1) {
+            if (m_mpz_manager.neq(get_value(as[0]), m_one))
+                return get_constants();
+        }
+
         m_temp_constants.reset();
 
         for (unsigned i = 0; i < sz; i++) {
-            expr * q = g->form(i);
+            expr * q = as[i];
             if (m_mpz_manager.eq(get_value(q), m_one))
                 continue;
             ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
@@ -1326,35 +1010,6 @@ public:
         return m_temp_constants;
     }
 
-    expr * get_unsat_assertion(goal_ref const & g, unsigned sz, unsigned int pos) {
-            for (unsigned i = pos; i < sz; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-                    return q;
-            }
-            for (unsigned i = 0; i < pos; i++) {
-                expr * q = g->form(i);
-                if (m_mpz_manager.neq(get_value(q), m_one))
-                    return q;
-            }
-            return 0;
-    }
-
-    ptr_vector<func_decl> & get_unsat_constants_walksat(goal_ref const & g, unsigned sz, unsigned int pos) {
-            expr * q = get_unsat_assertion(g, sz, pos);
-            // Andreas: I should probably fix this. If this is the case then the formula is SAT anyway but this is not checked in the first iteration.
-            if (!q)
-                return m_temp_constants;
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(q);
-            unsigned sz2 = this_decls.size();
-            for (unsigned j = 0; j < sz2; j++) {
-                func_decl * fd = this_decls[j];
-                if (!m_temp_constants.contains(fd))
-                    m_temp_constants.push_back(fd);
-            }
-            return m_temp_constants;
-    }
-
     ptr_vector<func_decl> & get_unsat_constants_walksat(expr * e) {
             if (!e || m_temp_constants.size())
                 return m_temp_constants;
@@ -1368,420 +1023,89 @@ public:
             return m_temp_constants;
     }
 
-    ptr_vector<func_decl> & go_deeper(expr * e) {
-            if (m_manager.is_bool(e)) {
-                if (m_manager.is_and(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    // Andreas: might be used for guided branching
-                    //for (unsigned i = 0; i < a->get_num_args(); i++) {
-                        //double cur = get_score(args[i]);
-                    //}
-                    // Andreas: A random number is better here since reusing flip will cause patterns.
-                    unsigned int sz = a->get_num_args();
-                    unsigned int pos = get_random_uint(16) % sz;
-                    for (unsigned int i = pos; i < sz; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                    for (unsigned int i = 0; i < pos; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                }
-                else if (m_manager.is_or(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    unsigned int sz = a->get_num_args();
-                    unsigned int pos = get_random_uint(16) % sz;
-                    for (unsigned int i = pos; i < sz; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                    for (unsigned int i = 0; i < pos; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one))
-                            return go_deeper(q);
-                    }
-                }
-            }
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
-            unsigned sz2 = this_decls.size();
-            for (unsigned j = 0; j < sz2; j++) {
-                func_decl * fd = this_decls[j];
-                if (!m_temp_constants.contains(fd))
-                    m_temp_constants.push_back(fd);
-            }
-            return m_temp_constants;
-    }
+    ptr_vector<func_decl> & get_unsat_constants(ptr_vector<expr> const & as) {
+        if (m_walksat)
+        {
+            expr * e = get_unsat_assertion(as);
 
-    ptr_vector<func_decl> & get_unsat_constants_crsat(goal_ref const & g, unsigned sz, unsigned int pos) {
-        expr * q = get_unsat_assertion(g, sz, pos);
-        if (!q)
-            return m_temp_constants;
-
-        return go_deeper(q);
-    }
-
-    void go_deeper_only(expr * e) {
-            //if (m_manager.is_bool(e)) {
-                if (m_manager.is_and(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    unsigned int sz = a->get_num_args();
-                    unsigned cnt_unsat = 0, pos = -1;
-                    for (unsigned int i = 0; i < sz; i++) {
-                        expr * q = args[i];
-                        if (m_mpz_manager.neq(get_value(q), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-                        //if (m_mpz_manager.neq(get_value(q), m_one)) go_deeper(q);
-                    }
-                    go_deeper(args[pos]);
-                }
-                else if (m_manager.is_or(e)) {
-                    app * a = to_app(e);
-                    expr * const * args = a->get_args();
-                    unsigned int sz = a->get_num_args();
-                    for (unsigned int i = 0; i < sz; i++) {
-                        expr * q = args[i];
-                        go_deeper(q);
-                    }
-                }
-            //}
-                else
-                {
-            ptr_vector<func_decl> const & this_decls = m_constants_occ.find(e);
-            unsigned sz2 = this_decls.size();
-            for (unsigned j = 0; j < sz2; j++) {
-                func_decl * fd = this_decls[j];
-                if (!m_temp_constants.contains(fd))
-                    m_temp_constants.push_back(fd);
-            }
-                }
-    }
-
-    ptr_vector<func_decl> & get_unsat_constants_only(expr * e) {
-            if (e && !m_temp_constants.size())
-                go_deeper_only(e);
-
-            return m_temp_constants;
-    }
-
-    ptr_vector<func_decl> & get_unsat_constants(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
-
-        if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(g->form(0)), m_one))
+            if (!e)
             {
                 m_temp_constants.reset();
                 return m_temp_constants;
             }
-            else
-                return get_constants();
-        }
-        else {
-            m_temp_constants.reset();
-#if _FOCUS_ == 1
-#if _UCT_
-            unsigned pos = -1;
-            value_score vscore;
-#if _PROBABILISTIC_UCT_
-            double sum_score = 0.0;
-            unsigned start_index = get_random_uint(16) % sz;
 
-            for (unsigned i = start_index; i < sz; i++)
-            {
-                expr * e = g->form(i);
-                vscore = m_scores.find(e);
-
-#if _PROBABILISTIC_UCT_ == 2
-                double q = vscore.score * vscore.score; 
-#else
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                    sum_score += q;
-                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                        pos = i;
-                }	
-            }
-            for (unsigned i = 0; i < start_index; i++)
-            {
-                expr * e = g->form(i);
-                vscore = m_scores.find(e);
-#if _PROBABILISTIC_UCT_ == 2
-                double q = vscore.score * vscore.score; 
-#else
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                    sum_score += q;
-                    if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                        pos = i;
-                }	
-            }
-#else
-            double max = -1.0;
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-//            for (unsigned i = 0; i < m_where_false.size(); i++) {
-//                expr * e = m_list_false[i];
-                vscore = m_scores.find(e);
-#if _UCT_ == 1
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched)/vscore.touched); 
-#elif _UCT_ == 2
-                double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
-#elif _UCT_ == 3
-                double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
-#endif
-                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
-            }
-#endif
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-
-#if _UCT_ == 1 || _UCT_ == 3
-            m_scores.find(g->form(pos)).touched++;
-            m_touched++;
-#elif _UCT_ == 2
-            m_scores.find(g->form(pos)).touched = flip; 
-#endif
-            expr * e = g->form(pos);
-//            expr * e = m_list_false[pos];
-
-#elif _BFS_ == 3
-            unsigned int pos = -1;
-            double max = -1.0;
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                double q = get_score(e);
-                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
-            }
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-            expr * e = g->form(pos);
-#elif _BFS_ == 2
-            unsigned int pos = -1;
-            double min = 2.0;
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                double q = get_score(e);
-                if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
-            }
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-            expr * e = g->form(pos);
-#elif _BFS_ == 1
-            // I guess it was buggy ...
-            // unsigned int pos = flip % m_constants.size();
-            unsigned int pos = flip % sz;
-            expr * e = get_unsat_assertion(g, sz, pos);
-#elif _UNIFORM_RANDOM_
-            unsigned cnt_unsat = 0, pos = -1;
-            for (unsigned i = 0; i < sz; i++)
-                if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-            if (pos == static_cast<unsigned>(-1))
-                return m_temp_constants;
-            expr * e = g->form(pos);
-#elif _REAL_RS_
-            //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-            //expr * e = get_unsat_assertion(g, sz, pos);
-            //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-            sz = m_where_false.size();
-            if (sz == 0)
-                return m_temp_constants;
-            expr * e = m_list_false[get_random_uint(16) % sz];
-#elif _REAL_PBFS_
-            //unsigned pos = m_false_list[flip % m_cnt_false];
-            //expr * e = get_unsat_assertion(g, sz, pos);
-            //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-            sz = m_where_false.size();
-            if (sz == 0)
-                return m_temp_constants;
-            else
-                expr * e = m_list_false[flip % sz];
-#else
-            // I guess it was buggy ...
-            // unsigned int pos = get_random_uint(16) % m_constants.size();
-            unsigned int pos = get_random_uint(16) % sz;
-            expr * e = get_unsat_assertion(g, sz, pos);
-#endif
             return get_unsat_constants_walksat(e);
-#elif _FOCUS_ == 2
-#if _BFS_
-            // I guess it was buggy ...
-            // unsigned int pos = flip % m_constants.size();
-            unsigned int pos = flip % sz;
-#else
-            // I guess it was buggy ...
-            // unsigned int pos = get_random_uint(16) % m_constants.size();
-            unsigned int pos = get_random_uint(16) % sz;
-#endif
-            return get_unsat_constants_crsat(g, sz, pos);
-#else
-            return get_unsat_constants_gsat(g, sz);
-#endif
         }
+        else
+            return get_unsat_constants_gsat(as);
     }
     
-    expr * get_unsat_assertion(goal_ref const & g, unsigned int flip) {
-        unsigned sz = g->size();
-
+    expr * get_unsat_assertion(ptr_vector<expr> const & as) {
+        unsigned sz = as.size();
         if (sz == 1) {
-            if (m_mpz_manager.eq(get_value(g->form(0)), m_zero))
-                return g->form(0);
+            if (m_mpz_manager.neq(get_value(as[0]), m_one))
+                return as[0];
             else
                 return 0;
         }
-
         m_temp_constants.reset();
-#if _FOCUS_ == 1
-#if _UCT_
+
         unsigned pos = -1;
-        value_score vscore;
-#if _PROBABILISTIC_UCT_
-        double sum_score = 0.0;
-        unsigned start_index = get_random_uint(16) % sz;
-            
-        for (unsigned i = start_index; i < sz; i++)
+        if (m_ucb)
         {
-            expr * e = g->form(i);
-            vscore = m_scores.find(e);
-#if _PROBABILISTIC_UCT_ == 2
-            double q = vscore.score * vscore.score + _UCT_EPS_; 
-#else
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                sum_score += q;
-                if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                    pos = i;
-            }	
-        }
-        for (unsigned i = 0; i < start_index; i++)
-        {
-            expr * e = g->form(i);
-            vscore = m_scores.find(e);
-#if _PROBABILISTIC_UCT_ == 2
-            double q = vscore.score * vscore.score + _UCT_EPS_; 
-#else
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + _UCT_EPS_; 
-#endif
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one)) {
-                sum_score += q;
-                if (rand() <= (q * RAND_MAX / sum_score) + 1)
-                    pos = i;
-            }	
-        }
-#else
-        double max = -1.0;
+            value_score vscore;
+            double max = -1.0;
             for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
+                expr * e = as[i];
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
-#if _UCT_ == 1
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log((double)m_touched) / vscore.touched);
-#elif _UCT_ == 2
-            double q = vscore.score + (_UCT_CONSTANT_ * (flip - vscore.touched)) / sz; 
-#elif _UCT_ == 3
+                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+#if _UCT_ == 3
             double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
 #endif
-            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
-#endif
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
+            if (pos == static_cast<unsigned>(-1))
+                return 0;
 
-#if _UCT_ == 1 || _UCT_ == 3
-        m_scores.find(g->form(pos)).touched++;
-        m_touched++;
-#elif _UCT_ == 2
-        m_scores.find(g->form(pos)).touched = flip; 
-#endif
+            m_scores.find(as[pos]).touched++;
+            m_touched++;
 //        return m_list_false[pos];
-        return g->form(pos);
-
-#elif _BFS_ == 3
-        unsigned int pos = -1;
-        double max = -1.0;
-        for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
-               double q = get_score(e);
-            if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
-        return g->form(pos);
-#elif _BFS_ == 2
-        unsigned int pos = -1;
-        double min = 2.0;
-        for (unsigned i = 0; i < sz; i++) {
-            expr * e = g->form(i);
-               double q = get_score(e);
-            if (q < min && m_mpz_manager.neq(get_value(e), m_one) ) { min = q; pos = i; }
         }
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
-        return g->form(pos);
-#elif _BFS_ == 1
-        unsigned int pos = flip % sz;
-        return get_unsat_assertion(g, sz, pos);
-#elif _UNIFORM_RANDOM_
-        unsigned cnt_unsat = 0, pos = -1;
-        for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
-        if (pos == static_cast<unsigned>(-1))
-            return 0;
-        return g->form(pos);
-#elif _REAL_RS_
+        else
+        {
+            unsigned cnt_unsat = 0;
+            for (unsigned i = 0; i < sz; i++)
+                if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
+            if (pos == static_cast<unsigned>(-1))
+                return 0;
+        }
+        
+        return as[pos];
+#if _REAL_RS_
         //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-        //expr * e = get_unsat_assertion(g, sz, pos);
         //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
         sz = m_where_false.size();
         if (sz == 0)
             return 0;
         return m_list_false[get_random_uint(16) % sz];
-#elif _REAL_PBFS_
-        //unsigned pos = m_false_list[flip % m_cnt_false];
-        //expr * e = get_unsat_assertion(g, sz, pos);
-        //expr * e = m_unsat_expr[flip % m_unsat_expr.size()];
-        sz = m_where_false.size();
-        if (sz == 0)
-            return0;
-        else
-            return m_list_false[flip % sz];
-#else
-        unsigned int pos = get_random_uint(16) % sz;
-        return get_unsat_assertion(g, sz, pos);
-#endif
-        return g->form(pos);
-#elif _FOCUS_ == 2
-#if _BFS_
-        unsigned int pos = flip % sz;
-#else
-        unsigned int pos = get_random_uint(16) % sz;
-#endif
-        return get_unsat_constants_crsat(g, sz, pos);
 #endif
     }
 
-    expr * get_new_unsat_assertion(goal_ref const & g, expr * e) {
-        unsigned sz = g->size();
-
+    expr * get_new_unsat_assertion(ptr_vector<expr> const & as, expr * e) {
+        unsigned sz = as.size();
         if (sz == 1)
             return 0;
-
         m_temp_constants.reset();
-
+        
         unsigned cnt_unsat = 0, pos = -1;
         for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(g->form(i)), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (g->form(i) != e)) pos = i;	
+            if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i;	
 
         if (pos == static_cast<unsigned>(-1))
             return 0;
-        return g->form(pos);
+        return as[pos];
     }
 };
 

From fb18547a5f12be7db71b04aea7198df2c5dcfad7 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 01:07:30 +0100
Subject: [PATCH 085/108] Fixed bug with VNS repick.

---
 src/tactic/sls/sls_compilation_settings.h |  2 +-
 src/tactic/sls/sls_engine.cpp             | 22 +++++++++++++++++-----
 src/tactic/sls/sls_tracker.h              |  7 ++++---
 3 files changed, 22 insertions(+), 9 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 9add78daa..a649bc9ed 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -23,7 +23,7 @@ Notes:
 #define _SLS_COMPILATION_SETTINGS_H_
 
 // shall we use addition/subtraction?
-#define _USE_ADDSUB_ 0
+#define _USE_ADDSUB_ 1
 
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index c240a0c51..af8ae1df2 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -68,6 +68,12 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_base = p.restart_base();
     m_restart_next = m_restart_base;
     m_restart_init = p.restart_init();
+
+    // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
+    if (m_walksat_repick && !m_walksat)
+        NOT_IMPLEMENTED_YET();
+    if (m_vns_repick && !m_walksat)
+        NOT_IMPLEMENTED_YET();
 }
 
 void sls_engine::checkpoint() {
@@ -435,19 +441,25 @@ lbool sls_engine::search() {
         if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
             score = find_best_move_mc(to_evaluate, score, new_const, new_value);
    
-        /*if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
+        if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
         {
-            expr * q = m_tracker.get_new_unsat_assertion(m_assertions, e);
+            expr * q = m_tracker.get_new_unsat_assertion(m_assertions);
             if (q)
             {
-                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(e);
+                ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q);
                 score = find_best_move(to_evaluate2, score, new_const, new_value, new_bit, move);
+
+                if (new_const != static_cast<unsigned>(-1)) {
+                    func_decl * fd = to_evaluate2[new_const];
+                    score = serious_score(fd, new_value);
+                    continue;
+                }
             }
-        }*/
+        }
 
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
-            if (m_walksat && m_walksat_repick)
+            if (m_walksat_repick)
                 m_evaluator.randomize_local(m_assertions);
             else
                 m_evaluator.randomize_local(to_evaluate);
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 65011dc8d..7b48057d4 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -76,7 +76,7 @@ private:
     ptr_vector<func_decl> m_constants;
     ptr_vector<func_decl> m_temp_constants;
     occ_type              m_constants_occ;
-
+    unsigned              m_last_pos;
     unsigned              m_walksat;
     unsigned              m_ucb;
     double                m_ucb_constant;
@@ -1082,6 +1082,7 @@ public:
                 return 0;
         }
         
+        m_last_pos = pos;
         return as[pos];
 #if _REAL_RS_
         //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
@@ -1093,7 +1094,7 @@ public:
 #endif
     }
 
-    expr * get_new_unsat_assertion(ptr_vector<expr> const & as, expr * e) {
+    expr * get_new_unsat_assertion(ptr_vector<expr> const & as) {
         unsigned sz = as.size();
         if (sz == 1)
             return 0;
@@ -1101,7 +1102,7 @@ public:
         
         unsigned cnt_unsat = 0, pos = -1;
         for (unsigned i = 0; i < sz; i++)
-            if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0) && (as[i] != e)) pos = i;	
+            if ((i != m_last_pos) && m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
 
         if (pos == static_cast<unsigned>(-1))
             return 0;

From ca1e3c3d9fe5974fbd2f358a40b6319250131ef2 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Tue, 22 Apr 2014 16:10:44 +0100
Subject: [PATCH 086/108] Backup before I touch early pruning ...

---
 src/tactic/sls/sls_compilation_settings.h |  3 ---
 src/tactic/sls/sls_engine.cpp             | 30 +++++++++++++----------
 src/tactic/sls/sls_engine.h               |  1 +
 src/tactic/sls/sls_evaluator.h            |  4 +--
 src/tactic/sls/sls_tracker.h              |  9 -------
 5 files changed, 19 insertions(+), 28 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index a649bc9ed..5c837b4b2 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,9 +22,6 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
 // should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
 #define _REAL_RS_ 0
 
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index af8ae1df2..5d4df237e 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -61,6 +61,7 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_walksat = p.walksat();
     m_walksat_repick = p.walksat_repick();
     m_paws_sp = p.paws_sp();
+    m_paws = m_paws_sp < 1024;
     m_wp = p.wp();
     m_vns_mc = p.vns_mc();
     m_vns_repick = p.vns_repick();
@@ -173,7 +174,6 @@ bool sls_engine::what_if(
 
     // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
-        m_tracker.reset_equal_scores();
         best_score = r;
         best_const = fd_inx;
         m_mpz_manager.set(best_value, temp);
@@ -244,16 +244,12 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
         m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
     else
     {
-#if _USE_ADDSUB_
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
         move_type mt = (move_type)rnd_mv;
 
         // inversion doesn't make sense, let's do a flip instead.
         if (mt == MV_INV) mt = MV_FLIP;
-#else
-        move_type mt = MV_FLIP;
-#endif
         unsigned bit = 0;
 
         switch (mt)
@@ -308,8 +304,9 @@ double sls_engine::find_best_move(
     unsigned bv_sz;
     double new_score = score;
 
-    m_tracker.reset_equal_scores();
-
+    //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size();
+    //for (unsigned j = 0; j < to_evaluate.size(); j++) {
+        //unsigned i = (j + offset) % to_evaluate.size();
     for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
@@ -328,7 +325,6 @@ double sls_engine::find_best_move(
         }
 
         if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
             if (!m_mpz_manager.is_even(old_value)) {
                 // for odd values, try +1
                 mk_inc(bv_sz, old_value, temp);
@@ -341,7 +337,6 @@ double sls_engine::find_best_move(
                 if (what_if(fd, i, temp, new_score, best_const, best_value))
                     move = MV_DEC;
             }
-#endif
             // try inverting
             mk_inv(bv_sz, old_value, temp);
             if (what_if(fd, i, temp, new_score, best_const, best_value))
@@ -418,7 +413,7 @@ lbool sls_engine::search() {
 #if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
 #endif
-        
+        // get candidate variables
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
         {
@@ -426,6 +421,7 @@ lbool sls_engine::search() {
             goto bailout;
         }
 
+        // random walk with probability wp / 1024
         if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
             mk_random_move(to_evaluate);
@@ -436,14 +432,18 @@ lbool sls_engine::search() {
         old_score = score;
         new_const = (unsigned)-1;
 
+        // find best increasing move
         score = find_best_move(to_evaluate, score, new_const, new_value, new_bit, move);
 
+        // use Monte Carlo 2-bit-flip sampling if no increasing move was found previously
         if (m_vns_mc && (new_const == static_cast<unsigned>(-1)))
             score = find_best_move_mc(to_evaluate, score, new_const, new_value);
    
+        // repick assertion if no increasing move was found previously
         if (m_vns_repick && (new_const == static_cast<unsigned>(-1)))
         {
             expr * q = m_tracker.get_new_unsat_assertion(m_assertions);
+            // only apply if another unsatisfied assertion actually exists
             if (q)
             {
                 ptr_vector<func_decl> & to_evaluate2 = m_tracker.get_unsat_constants_walksat(q);
@@ -457,6 +457,7 @@ lbool sls_engine::search() {
             }
         }
 
+        // randomize if no increasing move was found
         if (new_const == static_cast<unsigned>(-1)) {
             score = old_score;
             if (m_walksat_repick)
@@ -466,16 +467,19 @@ lbool sls_engine::search() {
 
             score = m_tracker.get_top_sum() / m_assertions.size();
 
-            if (m_paws_sp < 1024)
+            // update assertion weights if a weigthing is enabled (sp < 1024)
+            if (m_paws)
             {
                 for (unsigned i = 0; i < sz; i++)
                 {
                     expr * q = m_assertions[i];
+                    // smooth weights with probability sp / 1024
                     if (m_tracker.get_random_uint(10) < m_paws_sp)
                     {
                         if (m_mpz_manager.eq(m_tracker.get_value(q),m_one))
                             m_tracker.decrease_weight(q);
                     }
+                    // increase weights otherwise
                     else
                     {
                         if (m_mpz_manager.eq(m_tracker.get_value(q),m_zero))
@@ -484,6 +488,7 @@ lbool sls_engine::search() {
                 }
             }
         }
+        // otherwise, apply most increasing move
         else {
             func_decl * fd = to_evaluate[new_const];
             score = serious_score(fd, new_value);
@@ -507,7 +512,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     for (unsigned i = 0; i < g->size(); i++)
         assert_expr(g->form(i));    
 
-    verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
     verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
 
@@ -570,7 +574,7 @@ inline unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_next)
     {
-        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save 1 parameter.
+        /* Andreas: My own scheme (= 1) seems to work best. Other schemes are disabled so that we save one parameter.
         I leave the other versions as comments in case you want to try it again somewhen.
 #if _RESTART_SCHEME_ == 5
         m_restart_next += (unsigned)(m_restart_base * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index ff0e55f24..94f3fa626 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -76,6 +76,7 @@ protected:
     unsigned        m_wp;
     unsigned        m_vns_mc;
     unsigned        m_vns_repick;
+    unsigned        m_paws;
     unsigned        m_paws_sp;
     unsigned        m_restart_base;
     unsigned        m_restart_next;
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 37bfa5a2d..200a0e380 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -37,9 +37,7 @@ class sls_evaluator {
     powers              & m_powers;
     expr_ref_buffer       m_temp_exprs;
     vector<ptr_vector<expr> > m_traversal_stack;
-#if _EARLY_PRUNE_
     vector<ptr_vector<expr> > m_traversal_stack_bool;
-#endif
 
 public:
     sls_evaluator(ast_manager & m, bv_util & bvu, sls_tracker & t, unsynch_mpz_manager & mm, powers & p) : 
@@ -753,7 +751,7 @@ public:
 
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
-                // should always have uplinks ...
+                // Andreas: Should actually always have uplinks ...
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 7b48057d4..a815c9ad3 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -92,7 +92,6 @@ private:
 #endif
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
-    unsigned              m_equal_scores;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -148,14 +147,6 @@ public:
         return sum / count;   
     }
 
-    void reset_equal_scores() {
-        m_equal_scores = 1;
-    }
-
-    unsigned inc_equal_scores() {
-        return ++m_equal_scores;
-    }
-
     inline void adapt_top_sum(expr * e, double add, double sub) {
         m_top_sum += m_weights.find(e) * (add - sub);
     }

From 80c94ef0b63efe68d125fb7f6548da4630313db8 Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Wed, 23 Apr 2014 14:52:18 +0100
Subject: [PATCH 087/108] Moved parameters to the right file. Almost clean.

---
 src/tactic/sls/sls_compilation_settings.h |  5 +--
 src/tactic/sls/sls_engine.cpp             | 38 +++++++++++------------
 src/tactic/sls/sls_engine.h               |  3 +-
 src/tactic/sls/sls_evaluator.h            |  5 ---
 src/tactic/sls/sls_params.pyg             |  6 +---
 src/tactic/sls/sls_tracker.h              | 33 +++++++++-----------
 6 files changed, 36 insertions(+), 54 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 5c837b4b2..707802cf4 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -22,10 +22,7 @@ Notes:
 #ifndef _SLS_COMPILATION_SETTINGS_H_
 #define _SLS_COMPILATION_SETTINGS_H_
 
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
+// should we use unsat-structures as done in SLS 4 SAT?
 #define _REAL_RS_ 0
 
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
 #endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 5d4df237e..a1c72609c 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -70,6 +70,8 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_next = m_restart_base;
     m_restart_init = p.restart_init();
 
+    m_early_prune = p.early_prune();
+
     // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
     if (m_walksat_repick && !m_walksat)
         NOT_IMPLEMENTED_YET();
@@ -117,7 +119,7 @@ double sls_engine::top_score() {
 
     m_tracker.set_top_sum(top_sum);
 
-    return top_sum / (double)sz;
+    return top_sum;
 }
 
 double sls_engine::rescore() {
@@ -129,21 +131,21 @@ double sls_engine::rescore() {
 double sls_engine::serious_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.serious_update(fd, new_value);
     m_stats.m_incr_evals++;
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return m_tracker.get_top_sum();
 }
 
 double sls_engine::incremental_score(func_decl * fd, const mpz & new_value) {
     m_evaluator.update(fd, new_value);
     m_stats.m_incr_evals++;
-    return (m_tracker.get_top_sum() / m_assertions.size());
+    return m_tracker.get_top_sum();
 }
 
 double sls_engine::incremental_score_prune(func_decl * fd, const mpz & new_value) {
     m_stats.m_incr_evals++;
     if (m_evaluator.update_prune(fd, new_value))
-        return (m_tracker.get_top_sum() / m_assertions.size());
+        return m_tracker.get_top_sum();
     else
-        return 0.0;
+        return -DBL_MAX;
 }
 
 // checks whether the score outcome of a given move is better than the previous score
@@ -160,11 +162,11 @@ bool sls_engine::what_if(
     m_mpz_manager.set(old_value, m_tracker.get_value(fd));
 #endif
 
-#if _EARLY_PRUNE_
-    double r = incremental_score_prune(fd, temp);
-#else
-    double r = incremental_score(fd, temp);
-#endif   
+    double r;
+    if (m_early_prune)
+        r = incremental_score_prune(fd, temp);
+    else
+        r = incremental_score(fd, temp);
 #ifdef Z3DEBUG
     TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) <<
             " --> " << r << std::endl;);
@@ -342,11 +344,8 @@ double sls_engine::find_best_move(
             if (what_if(fd, i, temp, new_score, best_const, best_value))
                 move = MV_INV;
         }
-
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
-        // Andreas: does not hold anymore now that we use top level score caching
-        //SASSERT(check == score);
+        incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -381,9 +380,8 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
                 }
             }
         }
-
         // reset to what it was before
-        double check = incremental_score(fd, old_value);
+        incremental_score(fd, old_value);
     }
 
     m_mpz_manager.del(old_value);
@@ -408,7 +406,10 @@ lbool sls_engine::search() {
         checkpoint();
         m_stats.m_moves++;
         if (m_stats.m_moves % m_restart_base == 0)
+        {
             m_tracker.ucb_forget(m_assertions);
+            //score = rescore();
+        }
 
 #if _REAL_RS_
         //m_tracker.debug_real(g, m_stats.m_moves);
@@ -425,7 +426,7 @@ lbool sls_engine::search() {
         if (m_wp && m_tracker.get_random_uint(10) < m_wp)
         {
             mk_random_move(to_evaluate);
-            score = m_tracker.get_top_sum() / sz;
+            score = m_tracker.get_top_sum();
             continue;
         }
 
@@ -465,7 +466,7 @@ lbool sls_engine::search() {
             else
                 m_evaluator.randomize_local(to_evaluate);
 
-            score = m_tracker.get_top_sum() / m_assertions.size();
+            score = m_tracker.get_top_sum();
 
             // update assertion weights if a weigthing is enabled (sp < 1024)
             if (m_paws)
@@ -513,7 +514,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
         assert_expr(g->form(i));    
 
     verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-    verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
 
     lbool res = operator()();
 
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 94f3fa626..ac8610871 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -81,8 +81,7 @@ protected:
     unsigned        m_restart_base;
     unsigned        m_restart_next;
     unsigned        m_restart_init;
-
-    ptr_vector<mpz> m_old_values;
+    unsigned        m_early_prune;
 
     typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index 200a0e380..e4cf3c466 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -554,9 +554,7 @@ public:
                 if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
-#if _EARLY_PRUNE_
                 m_tracker.set_score_prune(cur, new_score);
-#endif            
 
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
@@ -599,9 +597,6 @@ public:
                 if (m_tracker.is_top_expr(cur))
                     m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
-#if _EARLY_PRUNE_
-                m_tracker.set_score_prune(cur, new_score);
-#endif            
                 if (m_tracker.has_uplinks(cur)) {
                     ptr_vector<expr> & ups = m_tracker.get_uplinks(cur);
                     for (unsigned j = 0; j < ups.size(); j++) {
diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index bf5bd181a..98875b20d 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -8,19 +8,15 @@ def_module_params('sls',
 						('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
 						('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'),
 						('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'),
-						('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'),
 						('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'),
 						('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'),
 						('paws_init', UINT, 40, 'initial/minimum assertion weights'),
 						('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'),
-						('wp', UINT, 100, 'random walk with probability wp / 1024'),
+						('wp', UINT, 0, 'random walk with probability wp / 1024'),
 						('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'),
 						('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'),
 						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
 						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
 						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
-						('random_offset', BOOL, 1, 'use random offset for candidate evaluation'),
-						('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'),
-						('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'),
 						('random_seed', UINT, 0, 'random seed')
 			  ))
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index a815c9ad3..507596273 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -44,11 +44,9 @@ class sls_tracker {
         unsynch_mpz_manager * m;
         mpz value;
         double score;
-#if _EARLY_PRUNE_
         double score_prune;
         unsigned has_pos_occ;
         unsigned has_neg_occ;
-#endif
         unsigned distance; // max distance from any root
         unsigned touched;
         value_score & operator=(const value_score & other) {
@@ -122,6 +120,7 @@ public:
         m_paws_init = p.paws_init();
     }
 
+    /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently.
     unsigned get_formula_size() {
         return m_scores.size();
     }
@@ -145,7 +144,7 @@ public:
         }
 
         return sum / count;   
-    }
+    }*/
 
     inline void adapt_top_sum(expr * e, double add, double sub) {
         m_top_sum += m_weights.find(e) * (add - sub);
@@ -417,6 +416,8 @@ public:
         }
     }
 
+    /* Andreas: Used this at some point to have values for the non-top-level expressions.
+                However, it did not give better performance but even cause some additional m/o - is not used currently.
     void initialize_recursive(init_proc proc, expr_mark visited, expr * e) {
         if (m_manager.is_and(e) || m_manager.is_or(e)) {
             app * a = to_app(e);
@@ -445,7 +446,7 @@ public:
         find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
         expr_fast_mark1 visited;
         quick_for_each_expr(ffd_proc, visited, e);
-    }
+    }*/
 
     void initialize(ptr_vector<expr> const & as) {
         init_proc proc(m_manager, *this);
@@ -455,8 +456,6 @@ public:
             expr * e = as[i];
             if (!m_top_expr.contains(e))
                 m_top_expr.insert(e);
-            else
-                printf("this is already in ...\n");
             for_each_expr(proc, visited, e);
         }
 
@@ -464,7 +463,6 @@ public:
 
         for (unsigned i = 0; i < sz; i++) {
             expr * e = as[i];
-            // Andreas: Maybe not fully correct.
             ptr_vector<func_decl> t;
             m_constants_occ.insert_if_not_there(e, t);
             find_func_decls_proc ffd_proc(m_manager, m_constants_occ.find(e));
@@ -488,15 +486,16 @@ public:
         for (unsigned i = 0; i < sz; i++)
         {
             expr * e = as[i];
-        	if (!m_weights.contains(e))
+
+            // initialize weights
+            if (!m_weights.contains(e))
         		m_weights.insert(e, m_paws_init);
+
+            // positive/negative occurences used for early pruning
+            setup_occs(as[i]);
         }
 
-#if _EARLY_PRUNE_
-        for (unsigned i = 0; i < sz; i++)
-            setup_occs(as[i]);
-#endif
-
+        // initialize ucb total touched value (individual ones are always initialized to 1)
         m_touched = m_ucb_init ? as.size() : 1;
     }
 
@@ -738,7 +737,6 @@ public:
             SASSERT(!negated);
             app * a = to_app(n);
             expr * const * args = a->get_args();
-            // Andreas: Seems to have no effect. Probably it is still too similar to the original version.
             double max = 0.0;
             for (unsigned i = 0; i < a->get_num_args(); i++) {
                 double cur = get_score(args[i]);
@@ -764,7 +762,6 @@ public:
             const mpz & v1 = get_value(arg1);
             
             if (negated) {                    
-                //res = (m_mpz_manager.eq(v0, v1)) ? 0.5 * (m_bv_util.get_bv_size(arg0) - 1.0) / m_bv_util.get_bv_size(arg0) : 1.0;
                 res = (m_mpz_manager.eq(v0, v1)) ? 0.0 : 1.0;
                 TRACE("sls_score", tout << "V0 = " << m_mpz_manager.to_string(v0) << " ; V1 = " << 
                                         m_mpz_manager.to_string(v1) << std::endl; );
@@ -1051,10 +1048,8 @@ public:
 //            for (unsigned i = 0; i < m_where_false.size(); i++) {
 //                expr * e = m_list_false[i];
                 vscore = m_scores.find(e);
-                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
-#if _UCT_ == 3
-            double q = vscore.score + _UCT_CONSTANT_ * sqrt(log(m_touched)/vscore.touched) + (get_random_uint(16) * 0.1 / (2<<16)); 
-#endif
+                //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); 
                 if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
             }
             if (pos == static_cast<unsigned>(-1))

From 7d18a17bb38ca701a49a17595e926dd5edf7933a Mon Sep 17 00:00:00 2001
From: Andreas Froehlich <t-anfro@microsoft.com>
Date: Fri, 25 Apr 2014 13:56:15 +0100
Subject: [PATCH 088/108] Cleaned up final SLS version. Enjoy!

---
 src/tactic/sls/sls_compilation_settings.h |  28 ----
 src/tactic/sls/sls_engine.cpp             |  43 ++++--
 src/tactic/sls/sls_engine.h               |   2 +
 src/tactic/sls/sls_evaluator.h            |   8 +-
 src/tactic/sls/sls_params.pyg             |   6 +-
 src/tactic/sls/sls_tracker.h              | 153 ++++++++--------------
 6 files changed, 94 insertions(+), 146 deletions(-)

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
index 707802cf4..e69de29bb 100644
--- a/src/tactic/sls/sls_compilation_settings.h
+++ b/src/tactic/sls/sls_compilation_settings.h
@@ -1,28 +0,0 @@
-/*++
-Copyright (c) 2014 Microsoft Corporation
-
-Module Name:
-
-    sls_compilation_constants.h
-
-Abstract:
-
-    Stochastic Local Search (SLS) compilation constants
-
-Author:
-
-    Christoph (cwinter) 2014-03-19
-
-Notes:
-
-    This file should go away completely once we have evaluated all options.
-
---*/
-
-#ifndef _SLS_COMPILATION_SETTINGS_H_
-#define _SLS_COMPILATION_SETTINGS_H_
-
-// should we use unsat-structures as done in SLS 4 SAT?
-#define _REAL_RS_ 0
-
-#endif
\ No newline at end of file
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index a1c72609c..269790902 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -71,6 +71,8 @@ void sls_engine::updt_params(params_ref const & _p) {
     m_restart_init = p.restart_init();
 
     m_early_prune = p.early_prune();
+    m_random_offset = p.random_offset();
+    m_rescore = p.rescore();
 
     // Andreas: Would cause trouble because repick requires an assertion being picked before which is not the case in GSAT.
     if (m_walksat_repick && !m_walksat)
@@ -174,6 +176,9 @@ bool sls_engine::what_if(
     m_mpz_manager.del(old_value);
 #endif
 
+    // Andreas: Had this idea on my last day. Maybe we could add a noise here similar to the one that worked so well for ucb assertion selection.
+    // r += 0.0001 * m_tracker.get_random_uint(8);
+
     // Andreas: For some reason it is important to use > here instead of >=. Probably related to prefering the LSB.
     if (r > best_score) {
         best_score = r;
@@ -248,9 +253,15 @@ void sls_engine::mk_random_move(ptr_vector<func_decl> & unsat_constants)
     {
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv = 2;
         if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
+
+        // Andreas: The other option would be to scale the probability for flips according to the bit-width.
+        /* unsigned bv_sz2 = m_bv_util.get_bv_size(srt);
+        rnd_mv = m_tracker.get_random_uint(16) % (bv_sz2 + 3);
+        if (rnd_mv > 3) rnd_mv = 0; */
+
         move_type mt = (move_type)rnd_mv;
 
-        // inversion doesn't make sense, let's do a flip instead.
+        // Andreas: Christoph claimed inversion doesn't make sense, let's do a flip instead. Is this really true?
         if (mt == MV_INV) mt = MV_FLIP;
         unsigned bit = 0;
 
@@ -306,10 +317,13 @@ double sls_engine::find_best_move(
     unsigned bv_sz;
     double new_score = score;
 
-    //unsigned offset = m_tracker.get_random_uint(16) % to_evaluate.size();
-    //for (unsigned j = 0; j < to_evaluate.size(); j++) {
-        //unsigned i = (j + offset) % to_evaluate.size();
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
+    unsigned sz = to_evaluate.size();
+    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
+    for (unsigned j = 0; j < sz; j++) {
+        unsigned i = j + offset;
+        if (i >= sz) i -= sz;
+    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -361,7 +375,13 @@ double sls_engine::find_best_move_mc(ptr_vector<func_decl> & to_evaluate, double
     unsigned bv_sz;
     double new_score = score;
 
-    for (unsigned i = 0; i < to_evaluate.size(); i++) {
+    // Andreas: Introducting a bit of randomization by using a random offset and a random direction to go through the candidate list.
+    unsigned sz = to_evaluate.size();
+    unsigned offset = (m_random_offset) ? m_tracker.get_random_uint(16) % sz : 0;
+    for (unsigned j = 0; j < sz; j++) {
+        unsigned i = j + offset;
+        if (i >= sz) i -= sz;
+    //for (unsigned i = 0; i < to_evaluate.size(); i++) {
         func_decl * fd = to_evaluate[i];
         sort * srt = fd->get_range();
         bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
@@ -405,15 +425,16 @@ lbool sls_engine::search() {
     while (check_restart(m_stats.m_moves)) {
         checkpoint();
         m_stats.m_moves++;
+
+        // Andreas: Every base restart interval ...
         if (m_stats.m_moves % m_restart_base == 0)
         {
+            // ... potentially smooth the touched counters ...
             m_tracker.ucb_forget(m_assertions);
-            //score = rescore();
+            // ... or normalize the top-level score.
+            if (m_rescore) score = rescore();
         }
 
-#if _REAL_RS_
-        //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
         // get candidate variables
         ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(m_assertions);
         if (!to_evaluate.size())
@@ -513,8 +534,6 @@ void sls_engine::operator()(goal_ref const & g, model_converter_ref & mc) {
     for (unsigned i = 0; i < g->size(); i++)
         assert_expr(g->form(i));    
 
-    verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-
     lbool res = operator()();
 
     if (res == l_true) {
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index ac8610871..8158808fa 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -82,6 +82,8 @@ protected:
     unsigned        m_restart_next;
     unsigned        m_restart_init;
     unsigned        m_early_prune;
+    unsigned        m_random_offset;
+    unsigned        m_rescore;
 
     typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV } move_type;
 
diff --git a/src/tactic/sls/sls_evaluator.h b/src/tactic/sls/sls_evaluator.h
index e4cf3c466..61afb7457 100644
--- a/src/tactic/sls/sls_evaluator.h
+++ b/src/tactic/sls/sls_evaluator.h
@@ -22,7 +22,6 @@ Notes:
 
 #include"model_evaluator.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 #include"sls_tracker.h"
 
@@ -540,19 +539,16 @@ public:
                 (*this)(to_app(cur), new_value);
                 m_tracker.set_value(cur, new_value);
 
-#if _REAL_RS_
+                new_score = m_tracker.score(cur);
                 if (m_tracker.is_top_expr(cur))
                 {
+                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                     if (m_mpz_manager.eq(new_value,m_one))
                         m_tracker.make_assertion(cur);
                     else
                         m_tracker.break_assertion(cur);
                 }
-#endif
 
-                new_score = m_tracker.score(cur);
-                if (m_tracker.is_top_expr(cur))
-                    m_tracker.adapt_top_sum(cur, new_score, m_tracker.get_score(cur));
                 m_tracker.set_score(cur, new_score);
                 m_tracker.set_score_prune(cur, new_score);
 
diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index 98875b20d..ad7a22675 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -8,15 +8,19 @@ def_module_params('sls',
 						('walksat_ucb_constant', DOUBLE, 20.0, 'the ucb constant c in the term score + c * f(touched)'),
 						('walksat_ucb_init', BOOL, 0, 'initialize total ucb touched to formula size'),
 						('walksat_ucb_forget', DOUBLE, 1.0, 'scale touched by this factor every base restart interval'),
+						('walksat_ucb_noise', DOUBLE, 0.0002, 'add noise 0 <= 256 * ucb_noise to ucb score for assertion selection'),
 						('walksat_repick', BOOL, 1, 'repick assertion if randomizing in local minima'),
 						('scale_unsat', DOUBLE, 0.5, 'scale score of unsat expressions by this factor'),
 						('paws_init', UINT, 40, 'initial/minimum assertion weights'),
 						('paws_sp', UINT, 52, 'smooth assertion weights with probability paws_sp / 1024'),
-						('wp', UINT, 0, 'random walk with probability wp / 1024'),
+						('wp', UINT, 100, 'random walk with probability wp / 1024'),
 						('vns_mc', UINT, 0, 'in local minima, try Monte Carlo sampling vns_mc many 2-bit-flips per bit'),
 						('vns_repick', BOOL, 0, 'in local minima, try picking a different assertion (only for walksat)'),
 						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
 						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
 						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
+						('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'),
+						('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'),
+						('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'),
 						('random_seed', UINT, 0, 'random seed')
 			  ))
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 507596273..4356bcc9b 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -80,14 +80,13 @@ private:
     double                m_ucb_constant;
     unsigned              m_ucb_init;
     double                m_ucb_forget;
+    double                m_ucb_noise;
     unsigned              m_touched;
     double                m_scale_unsat;
     unsigned              m_paws_init;
-#if _REAL_RS_
-    ptr_vector<expr>	  m_unsat_expr;
     obj_map<expr, unsigned>	m_where_false;
     expr**					m_list_false;
-#endif
+    unsigned              m_track_unsat;
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
 
@@ -116,8 +115,12 @@ public:
         m_ucb_constant = p.walksat_ucb_constant();
         m_ucb_init = p.walksat_ucb_init();
         m_ucb_forget = p.walksat_ucb_forget();
+        m_ucb_noise = p.walksat_ucb_noise();
         m_scale_unsat = p.scale_unsat();
         m_paws_init = p.paws_init();
+        // Andreas: track_unsat is currently disabled because I cannot guarantee that it is not buggy.
+        // If you want to use it, you will also need to change comments in the assertion selection.
+        m_track_unsat = 0;//p.track_unsat();
     }
 
     /* Andreas: Tried to give some measure for the formula size by the following two methods but both are not used currently.
@@ -254,53 +257,6 @@ public:
         return m_uplinks.find(n);
     }
 
-#if _REAL_RS_
-    void debug_real(goal_ref const & g, unsigned flip)
-    {
-        unsigned count = 0;
-        for (unsigned i = 0; i < g->size(); i++)
-        {
-            expr * e = g->form(i);
-            if (m_mpz_manager.eq(get_value(e),m_one) && m_where_false.contains(e))
-            {
-                printf("iteration %d: ", flip);
-                printf("form %d is sat but in unsat list at position %d of %d\n", i, m_where_false.find(e), m_where_false.size());
-                exit(4);
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero) && !m_where_false.contains(e))
-            {
-                printf("iteration %d: ", flip);
-                printf("form %d is unsat but not in unsat list\n", i);
-                exit(4);
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero) && m_where_false.contains(e))
-            {
-                unsigned pos = m_where_false.find(e);
-                expr * q = m_list_false[pos];
-                if (q != e)
-                {
-                    printf("iteration %d: ", flip);
-                    printf("form %d is supposed to be at pos %d in unsat list but something else was there\n", i, pos);
-                    exit(4);
-                }
-            }
-
-            if (m_mpz_manager.eq(get_value(e),m_zero))
-                count++;
-        }
-
-        // should be true now that duplicate assertions are removed
-        if (count != m_where_false.size())
-        {
-                printf("iteration %d: ", flip);
-                printf("%d are unsat but list is of size %d\n", count, m_where_false.size());
-                exit(4);
-        }
-    }
-#endif
-
     inline void ucb_forget(ptr_vector<expr> & as) {
         if (m_ucb_forget < 1.0)
         {
@@ -474,14 +430,15 @@ public:
 
         TRACE("sls", tout << "Initial model:" << std::endl; show_model(tout); );
 
-#if _REAL_RS_
-        m_list_false = new expr*[sz];
-        //for (unsigned i = 0; i < sz; i++)
-        //{
-        //	if (m_mpz_manager.eq(get_value(g->form(i)),m_zero))
-        //		break_assertion(g->form(i));
-        //}
-#endif
+        if (m_track_unsat)
+        {
+            m_list_false = new expr*[sz];
+            for (unsigned i = 0; i < sz; i++)
+            {
+        	    if (m_mpz_manager.eq(get_value(as[i]), m_zero))
+                    break_assertion(as[i]);
+            }
+        }
 
         for (unsigned i = 0; i < sz; i++)
         {
@@ -515,44 +472,36 @@ public:
         return m_weights.find(e);
     }
 
-#if _REAL_RS_
     void make_assertion(expr * e)
     {
-        if (m_where_false.contains(e))
+        if (m_track_unsat)
         {
-            unsigned pos = m_where_false.find(e);
-            m_where_false.erase(e);
-            if (pos != m_where_false.size())
+            if (m_where_false.contains(e))
             {
-                expr * q = m_list_false[m_where_false.size()];
-                m_list_false[pos] = q;
-                m_where_false.find(q) = pos;
-                //printf("Moving %d from %d to %d\n", q, m_where_false.size(), pos);
+                unsigned pos = m_where_false.find(e);
+                m_where_false.erase(e);
+                if (pos != m_where_false.size())
+                {
+                    expr * q = m_list_false[m_where_false.size()];
+                    m_list_false[pos] = q;
+                    m_where_false.find(q) = pos;
+                }
             }
-            //else
-                //printf("Erasing %d from %d to %d\n", e, pos);
-//			m_list_false[m_where_false.size()] = 0;
-//			printf("Going in %d\n", m_where_false.size());
         }
-        //if (m_unsat_expr.contains(e))
-            //m_unsat_expr.erase(e);
     }
 
     void break_assertion(expr * e)
     {
-        //printf("I'm broken... that's still fine.\n");
-        if (!m_where_false.contains(e))
+        if (m_track_unsat)
         {
-            //printf("This however is not so cool...\n");
-            unsigned pos = m_where_false.size();
-            m_list_false[pos] = e;
-            m_where_false.insert(e, pos);
-    //		printf("Going in %d\n", m_where_false.size());
+            if (!m_where_false.contains(e))
+            {
+                unsigned pos = m_where_false.size();
+                m_list_false[pos] = e;
+                m_where_false.insert(e, pos);
+            }
         }
-        //if (!m_unsat_expr.contains(e))
-            //m_unsat_expr.push_back(e);
     }
-#endif
 
     void show_model(std::ostream & out) {
         unsigned sz = get_num_constants();
@@ -1043,24 +992,38 @@ public:
         {
             value_score vscore;
             double max = -1.0;
+            // Andreas: Commented things here might be used for track_unsat data structures as done in SLS for SAT. But seems to have no benefit.
+            /* for (unsigned i = 0; i < m_where_false.size(); i++) {
+                expr * e = m_list_false[i]; */
             for (unsigned i = 0; i < sz; i++) {
                 expr * e = as[i];
-//            for (unsigned i = 0; i < m_where_false.size(); i++) {
-//                expr * e = m_list_false[i];
-                vscore = m_scores.find(e);
-                //double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
-                double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + (get_random_uint(8) * 0.0000002); 
-                if (q > max && m_mpz_manager.neq(get_value(e), m_one) ) { max = q; pos = i; }
+                if (m_mpz_manager.neq(get_value(e), m_one))
+                {
+                    vscore = m_scores.find(e);
+                    // Andreas: Select the assertion with the greatest ucb score. Potentially add some noise.
+                    // double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched);
+                    double q = vscore.score + m_ucb_constant * sqrt(log((double)m_touched) / vscore.touched) + m_ucb_noise * get_random_uint(8); 
+                    if (q > max) { max = q; pos = i; }
+                }
             }
             if (pos == static_cast<unsigned>(-1))
                 return 0;
 
-            m_scores.find(as[pos]).touched++;
             m_touched++;
-//        return m_list_false[pos];
+            m_scores.find(as[pos]).touched++;
+            // Andreas: Also part of track_unsat data structures. Additionally disable the previous line!
+            /* m_last_pos = pos;
+            m_scores.find(m_list_false[pos]).touched++;
+            return m_list_false[pos]; */
         }
         else
         {
+            // Andreas: The track_unsat data structures for random assertion selection.
+            /* sz = m_where_false.size();
+            if (sz == 0)
+                return 0;
+            return m_list_false[get_random_uint(16) % sz]; */
+
             unsigned cnt_unsat = 0;
             for (unsigned i = 0; i < sz; i++)
                 if (m_mpz_manager.neq(get_value(as[i]), m_one) && (get_random_uint(16) % ++cnt_unsat == 0)) pos = i;	
@@ -1070,14 +1033,6 @@ public:
         
         m_last_pos = pos;
         return as[pos];
-#if _REAL_RS_
-        //unsigned pos = m_false_list[get_random_uint(16) % m_cnt_false];
-        //expr * e = m_unsat_expr[get_random_uint(16) % m_unsat_expr.size()];
-        sz = m_where_false.size();
-        if (sz == 0)
-            return 0;
-        return m_list_false[get_random_uint(16) % sz];
-#endif
     }
 
     expr * get_new_unsat_assertion(ptr_vector<expr> const & as) {

From 992d150b8180c8d0e5b059e3c4c186f35dae7d7c Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 17:17:47 +0100
Subject: [PATCH 089/108] BVSLS comments

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_params.pyg | 2 +-
 src/tactic/sls/sls_tracker.h  | 4 +++-
 2 files changed, 4 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_params.pyg b/src/tactic/sls/sls_params.pyg
index ad7a22675..bf5bd181a 100644
--- a/src/tactic/sls/sls_params.pyg
+++ b/src/tactic/sls/sls_params.pyg
@@ -19,7 +19,7 @@ def_module_params('sls',
 						('restart_base', UINT, 100, 'base restart interval given by moves per run'),
 						('restart_init', BOOL, 0, 'initialize to 0 or random value (= 1) after restart'),
 						('early_prune', BOOL, 1, 'use early pruning for score prediction'),
-						('random_offset', BOOL, 1, 'use random offset vor candidate evaluation'),
+						('random_offset', BOOL, 1, 'use random offset for candidate evaluation'),
 						('rescore', BOOL, 1, 'rescore/normalize top-level score every base restart interval'),
 						('track_unsat', BOOL, 0, 'keep a list of unsat assertions as done in SAT - currently disabled internally'),
 						('random_seed', UINT, 0, 'random seed')
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 4356bcc9b..d58f94af2 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -831,7 +831,9 @@ public:
             app * a = to_app(n);
             SASSERT(a->get_num_args() == 1);
             expr * child = a->get_arg(0);
-            if (m_manager.is_and(child) || m_manager.is_or(child)) // Precondition: Assertion set is in NNF.
+            // Precondition: Assertion set is in NNF.
+            // Also: careful about the unsat assertion scaling further down.
+            if (m_manager.is_and(child) || m_manager.is_or(child)) 
                 NOT_IMPLEMENTED_YET();
             res = score_bool(child, true);
         }

From bec5938d9c06be6512ab2df49134ce33d09c0eb2 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 18:03:35 +0100
Subject: [PATCH 090/108] removed unused file

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_compilation_settings.h | 0
 src/tactic/sls/sls_engine.cpp             | 1 -
 src/tactic/sls/sls_engine.h               | 1 -
 src/tactic/sls/sls_tracker.h              | 1 -
 4 files changed, 3 deletions(-)
 delete mode 100644 src/tactic/sls/sls_compilation_settings.h

diff --git a/src/tactic/sls/sls_compilation_settings.h b/src/tactic/sls/sls_compilation_settings.h
deleted file mode 100644
index e69de29bb..000000000
diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 269790902..67dba0237 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -27,7 +27,6 @@ Notes:
 #include"cooperate.h"
 #include"luby.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_params.hpp"
 #include"sls_engine.h"
 
diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8158808fa..8a8a57e0e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -24,7 +24,6 @@ Notes:
 #include"model_converter.h"
 #include"goal.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_tracker.h"
 #include"sls_evaluator.h"
 
diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index d58f94af2..186fae250 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -25,7 +25,6 @@ Notes:
 #include"bv_decl_plugin.h"
 #include"model.h"
 
-#include"sls_compilation_settings.h"
 #include"sls_powers.h"
 
 class sls_tracker {

From 7a7566f39e183f8cc5cbe9f1ae251f96aafc1e6f Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 18:11:30 +0100
Subject: [PATCH 091/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 186fae250..73355197a 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -25,6 +25,7 @@ Notes:
 #include"bv_decl_plugin.h"
 #include"model.h"
 
+#include"sls_params.hpp"
 #include"sls_powers.h"
 
 class sls_tracker {
@@ -1052,4 +1053,4 @@ public:
     }
 };
 
-#endif
\ No newline at end of file
+#endif

From 7105e4d213ded77b3be3e8d9ea13b0a40076f0fa Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 21:49:35 +0100
Subject: [PATCH 092/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.h | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_engine.h b/src/tactic/sls/sls_engine.h
index 8a8a57e0e..b056c438e 100644
--- a/src/tactic/sls/sls_engine.h
+++ b/src/tactic/sls/sls_engine.h
@@ -136,8 +136,8 @@ protected:
 
     void mk_random_move(ptr_vector<func_decl> & unsat_constants);
 
-    //inline double get_restart_armin(unsigned cnt_restarts);    
-    inline unsigned check_restart(unsigned curr_value);
+    //double get_restart_armin(unsigned cnt_restarts);    
+    unsigned check_restart(unsigned curr_value);
 };
 
 #endif

From 0016ba5f3e768d2669dc41a3b951b5d34269d329 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 21:54:08 +0100
Subject: [PATCH 093/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 67dba0237..5b32e5790 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -16,6 +16,7 @@ Author:
 Notes:
 
 --*/
+#include<float.h>
 #include<iomanip>
 
 #include"map.h"

From 8745872d28db43740c5e3fe029375f1a3cf1ba36 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 25 Apr 2014 22:03:26 +0100
Subject: [PATCH 094/108] compilation fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_engine.cpp | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/tactic/sls/sls_engine.cpp b/src/tactic/sls/sls_engine.cpp
index 5b32e5790..c0c319ab4 100644
--- a/src/tactic/sls/sls_engine.cpp
+++ b/src/tactic/sls/sls_engine.cpp
@@ -581,7 +581,7 @@ lbool sls_engine::operator()() {
 }
 
 /* Andreas: Needed for Armin's restart scheme if we don't want to use loops.
-inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
+double sls_engine::get_restart_armin(unsigned cnt_restarts)
 {
     unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
     unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
@@ -589,7 +589,7 @@ inline double sls_engine::get_restart_armin(unsigned cnt_restarts)
 }    
 */
 
-inline unsigned sls_engine::check_restart(unsigned curr_value)
+unsigned sls_engine::check_restart(unsigned curr_value)
 {
     if (curr_value > m_restart_next)
     {

From 85ff954bc6d4f87ecb5adbf2063980fbe0eb879f Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Thu, 11 Sep 2014 00:27:37 +0100
Subject: [PATCH 095/108] merge fix

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tactic.cpp | 1413 +--------------------------------
 1 file changed, 30 insertions(+), 1383 deletions(-)

diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 6e1102dd2..9bbed20bb 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -16,1378 +16,30 @@ Author:
 Notes:
 
 --*/
-#include<iomanip>
-#include"map.h"
 #include"nnf.h"
-#include"cooperate.h"
-#include"ast_smt2_pp.h"
-#include"ast_pp.h"
-#include"var_subst.h"
-#include"model_pp.h"
-#include"model_evaluator.h"
 #include"solve_eqs_tactic.h"
-#include"elim_uncnstr_tactic.h"
 #include"bv_size_reduction_tactic.h"
 #include"max_bv_sharing_tactic.h"
 #include"simplify_tactic.h"
-#include"stopwatch.h"
 #include"propagate_values_tactic.h"
-#include"sls_tactic.h"
+#include"ctx_simplify_tactic.h"
+#include"elim_uncnstr_tactic.h"
 #include"nnf_tactic.h"
-#include"luby.h"
-#include "ctx_simplify_tactic.h"
-
-// which unsatisfied assertion is selected? only works with _FOCUS_ > 0
-// 0 = random, 1 = #moves, 2 = assertion with min score, 3 = assertion with max score
-#define _BFS_ 0
-
-// how many terms are considered for variable selection?
-// 0 = all terms (GSAT), 1 = only one top level assertion (WSAT), 2 = only one bottom level atom
-#define _FOCUS_ 1
-
-// probability of choosing the same assertion again in the next step
-#define _PERC_STICKY_ 0
-
-// do we use dirty unit propagation to get rid of nested top level assertions?
-#define _DIRTY_UP_ 1
-
-// do we use restarts?
-// 0 = no, 1 = use #moves, 2 = use #plateaus, 3 = use time
-#define _RESTARTS_ 3
-// limit of moves/plateaus/seconds until first restart occurs
-#define _RESTART_LIMIT_ 10
-// 0 = initialize with all zero, 1 initialize with random value
-#define _RESTART_INIT_ 0
-// 0 = even intervals, 1 = pseudo luby, 2 = real luby, 3 = armin, 4 = rapid, 5 = minisat
-#define _RESTART_SCHEME_ 1
-// base value c for armin restart scheme using c^inner - only applies for _RESTART_SCHEME_ 3
-#define _RESTART_CONST_ARMIN_ 4.0
-
-// timelimit
-#define _TIMELIMIT_ 3600
-
-// should score of conjunctions be calculated by average rather than max?
-#define _SCORE_AND_AVG_ 0
-
-// should score of discunctions be calculated by multiplication of the inverse score rather than min?
-#define _SCORE_OR_MUL_ 0
-
-// do we use some kind of variable neighbourhood-search?
-// 0 = no, 1 = only consider flipping bits if no better score can be obtained otherwise, 2 = only consider flipping bits until a better score can be obtained
-#define _VNS_ 0
-
-// do we reduce the score of unsatisfied literals?
-// 0 = no
-// 1 = yes, by multiplying it with some factor
-// 2 = yes, by squaring it
-// 3 = yes, by setting it to zero
-// 4 = by progessively increasing weight (_TIMELIMIT_ needs to be set appropriately!)
-#define _WEIGHT_DIST_ 1
-
-// the factor used for _WEIGHT_DIST_ = 1
-#define _WEIGHT_DIST_FACTOR_ 0.5
-
-// shall we toggle the weight after each restart?
-#define _WEIGHT_TOGGLE_ 0
-
-// do we use intensification steps in local minima? if so, how many?
-#define _INTENSIFICATION_ 0
-#define _INTENSIFICATION_TRIES_ 0
-
-// what is the percentage of random moves in plateaus (instead of full randomization)?
-#define _PERC_PLATEAU_MOVES_ 0
-
-// shall we repick clause when randomizing in a plateau or use the current one?
-#define _REPICK_ 1
-
-// do we use some UCT-like scheme for assertion-selection? overrides _BFS_
-#define _UCT_ 1
-
-// how much diversification is used in the UCT-scheme?
-#define _UCT_CONSTANT_ 20.0
-
-// is uct clause selection probabilistic similar to variable selection in sparrow?
-// 0 = no, 1 = yes, use uct-value, 2 = yes, use score-value (_UCT_CONSTANT_ = 0.0) with squared score
-#define _PROBABILISTIC_UCT_ 0
-
-// additive constants for probabilistic uct > 0
-#define _UCT_EPS_ 0.0001
-
-// shall we reset _UCT_ touched values after restart?
-#define _UCT_RESET_ 0
-
-// do we gradually reduce the touched values of _UCT_?
-#define _UCT_FORGET_ 0
-#define _UCT_FORGET_FACTOR_ 0.5
-
-// how shall we initialize the _UCT_ total touched counter?
-// 0 = initialize with one, 1 = initialize with number of assertions
-#define _UCT_INIT_ 0
-
-// shall we use addition/subtraction?
-#define _USE_ADDSUB_ 1
-
-// shall we try multilication and division by 2?
-#define _USE_MUL2DIV2_ 0
-
-// shall we try multiplication by 3?
-#define _USE_MUL3_ 0
-
-// shall we try unary minus (= inverting and incrementing)
-#define _USE_UNARY_MINUS_ 0
-
-// is random selection for assertions uniform? only works with _BFS_ = _UCT_ = 0
-#define _UNIFORM_RANDOM_ 0
-
-// should we use unsat-structures as done in SLS 4 SAT instead for random or bfs selection?
-#define _REAL_RS_ 0
-#define _REAL_PBFS_ 0
-
-// how many bits do we neglect in each iteration?
-#define _SKIP_BITS_ 0
-
-// when randomizing local, what is the probability for changing a single bit?
-// 0 = use standard scheme and pick a new value at random (= 50), otherwise the value (as int) gives the percentage
-#define _PERC_CHANGE_ 0
-
-// do we use random steps for noise?
-// 0 = no, 1 = randomize local, 2 = make random move
-#define _TYPE_RSTEP_ 0
-
-// with what probability _PERM_STEP_/1000 will the random step happen? 
-#define _PERM_RSTEP_ 0
-
-// shall we use early pruning for incremental update?
-#define _EARLY_PRUNE_ 1
-
-// shall we use caching for top_score?
-#define _CACHE_TOP_SCORE_ 1
-
-
-#if ((_BFS_ > 0) + (_UCT_ > 0) + _UNIFORM_RANDOM_ + _REAL_RS_ + _REAL_PBFS_ > 1)
-    InvalidConfiguration;
-#endif
-#if (_PROBABILISTIC_UCT_ && !_UCT_)
-    InvalidConfiguration;
-#endif
-#if (_PERM_RSTEP_ && !_TYPE_RSTEP_)
-    InvalidConfiguration;
-#endif
-#if (_PERC_CHANGE_ == 50)
-    InvalidConfiguration;
-#endif
-#if (_PERC_STICKY_ && !_FOCUS_)
-    InvalidConfiguration;
-#endif
-
+#include"stopwatch.h"
+#include"sls_tactic.h"
 #include"sls_params.hpp"
-#include"sls_evaluator.h"
-#include"sls_tracker.h"
+#include"sls_engine.h"
 
-class sls_tactic : public tactic {
-    class stats {
-    public:
-        unsigned        m_restarts;
-        stopwatch       m_stopwatch;    
-        unsigned        m_full_evals;
-        unsigned        m_incr_evals;
-        unsigned        m_moves, m_flips, m_incs, m_decs, m_invs, m_umins, m_mul2s, m_mul3s, m_div2s;
-
-        stats() :
-            m_restarts(0),
-            m_full_evals(0),
-            m_incr_evals(0),
-            m_moves(0),
-            m_umins(0),
-            m_mul2s(0),
-            m_mul3s(0),
-            m_div2s(0),
-            m_flips(0),
-            m_incs(0),
-            m_decs(0),
-            m_invs(0) {
-                m_stopwatch.reset();
-                m_stopwatch.start();
-            }
-        void reset() {
-            m_full_evals = m_flips = m_incr_evals = 0;
-            m_stopwatch.reset();
-            m_stopwatch.start();
-        }
-    };    
-
-    struct imp {       
-        ast_manager   & m_manager;
-        stats         & m_stats;
-        unsynch_mpz_manager m_mpz_manager;
-        powers          m_powers;
-        mpz             m_zero, m_one, m_two;            
-        bool            m_produce_models;
-        volatile bool   m_cancel;    
-        bv_util         m_bv_util;
-        sls_tracker     m_tracker;
-        sls_evaluator   m_evaluator;
-
-        unsigned		m_restart_limit;
-        unsigned        m_max_restarts;
-        unsigned        m_plateau_limit;
-
-        ptr_vector<mpz> m_old_values;
-        
-        typedef enum { MV_FLIP = 0, MV_INC, MV_DEC, MV_INV, MV_UMIN, MV_MUL2, MV_MUL3, MV_DIV2 } move_type;        
-
-        imp(ast_manager & m, params_ref const & p, stats & s) : 
-            m_manager(m),
-            m_stats(s),
-            m_powers(m_mpz_manager),
-            m_zero(m_mpz_manager.mk_z(0)),
-            m_one(m_mpz_manager.mk_z(1)),
-            m_two(m_mpz_manager.mk_z(2)),
-            m_cancel(false),
-            m_bv_util(m),
-            m_tracker(m, m_bv_util, m_mpz_manager, m_powers),
-            m_evaluator(m, m_bv_util, m_tracker, m_mpz_manager, m_powers) 
-        {
-            updt_params(p);
-        }
-
-        ~imp() {
-            m_mpz_manager.del(m_zero);
-            m_mpz_manager.del(m_one);
-            m_mpz_manager.del(m_two);
-        }        
-
-        double get_restart_armin(unsigned cnt_restarts)
-        {
-            unsigned outer_id = (unsigned)(0.5 + sqrt(0.25 + 2 * cnt_restarts));
-            unsigned inner_id = cnt_restarts - (outer_id - 1) * outer_id / 2;
-            //printf("armin: %f\n", pow(1.1, inner_id + 1));
-            return pow(_RESTART_CONST_ARMIN_, inner_id + 1);
-        }
-
-        inline unsigned check_restart(unsigned curr_value)
-        {
-            if (curr_value > m_restart_limit)
-            {
-#if _RESTART_SCHEME_ == 5
-                m_restart_limit += (unsigned)(_RESTART_LIMIT_ * pow(_RESTART_CONST_ARMIN_, m_stats.m_restarts));
-#elif _RESTART_SCHEME_ == 4
-                m_restart_limit += (m_stats.m_restarts & (m_stats.m_restarts + 1)) ? _RESTART_LIMIT_ : (_RESTART_LIMIT_ * m_stats.m_restarts + 1);
-#elif _RESTART_SCHEME_ == 3
-                m_restart_limit += (unsigned)get_restart_armin(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 2
-                m_restart_limit += get_luby(m_stats.m_restarts + 1) * _RESTART_LIMIT_;
-#elif _RESTART_SCHEME_ == 1
-                if (m_stats.m_restarts & 1)
-                    m_restart_limit += _RESTART_LIMIT_;
-                else
-                    m_restart_limit += (2 << (m_stats.m_restarts >> 1)) * _RESTART_LIMIT_;
-#else
-                    m_restart_limit += _RESTART_LIMIT_;
-#endif
-#if _WEIGHT_TOGGLE_
-                    printf("Setting weight: %f\n", _WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-                m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_ * (((m_stats.m_restarts & 2) == 0) + 1));
-#endif
-                return 0;
-            }
-            return 1;
-        }
-
-        ast_manager & m() const { return m_manager; }
-
-        void set_cancel(bool f) { m_cancel = f; }
-        void cancel() { set_cancel(true); }
-        void reset_cancel() { set_cancel(false); }
-
-        static void collect_param_descrs(param_descrs & r) {
-            sls_params::collect_param_descrs(r);
-        }
-
-        void updt_params(params_ref const & _p) {
-            sls_params p(_p);
-            m_produce_models = _p.get_bool("model", false);
-            m_max_restarts = p.restarts();            
-            m_tracker.set_random_seed(p.random_seed());
-            m_plateau_limit = p.plateau_limit();
-        }
-
-        void checkpoint() { 
-            if (m_cancel)
-                throw tactic_exception(TACTIC_CANCELED_MSG);
-            cooperate("sls");
-        }
-
-        bool full_eval(goal_ref const & g, model & mdl) {
-            bool res = true;
-
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz && res; i++) {
-                checkpoint();
-                expr_ref o(m_manager);
-
-                if (!mdl.eval(g->form(i), o, true))
-                    exit(ERR_INTERNAL_FATAL);
-
-                res = m_manager.is_true(o.get());
-            }        
-
-            TRACE("sls", tout << "Evaluation: " << res << std::endl;);
-
-            return res;
-        }
-
-        double top_score(goal_ref const & g) {
-            #if 0
-            double min = m_tracker.get_score(g->form(0));
-            unsigned sz = g->size();
-            for (unsigned i = 1; i < sz; i++) {
-                double q = m_tracker.get_score(g->form(i));
-                if (q < min) min = q;
-            }
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                for (unsigned i = 0; i < sz; i++)
-                                    tout << " " << m_tracker.get_score(g->form(i));
-                                tout << " MIN: " << min << std::endl; );
-            return min;
-            #else
-            double top_sum = 0.0;
-            unsigned sz = g->size();
-            for (unsigned i = 0; i < sz; i++) {
-                expr * e = g->form(i);
-                top_sum += m_tracker.get_score(e);
-            }
-
-            TRACE("sls_top", tout << "Score distribution:"; 
-                                    for (unsigned i = 0; i < sz; i++)
-                                        tout << " " << m_tracker.get_score(g->form(i));
-                                    tout << " AVG: " << top_sum / (double) sz << std::endl; );
-
-#if _CACHE_TOP_SCORE_
-            m_tracker.set_top_sum(top_sum);
-#endif
-
-            return top_sum / (double) sz;
-            #endif
-        }
-
-        double rescore(goal_ref const & g) {
-            m_evaluator.update_all();
-            m_stats.m_full_evals++;
-            return top_score(g);
-        }
-
-        double serious_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.serious_update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-        double incremental_score(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_evaluator.update(fd, new_value);
-            m_stats.m_incr_evals++;
-#if _CACHE_TOP_SCORE_
-            return (m_tracker.get_top_sum() / g->size());
-#else
-            return top_score(g);
-#endif
-        }
-
-#if _EARLY_PRUNE_
-        double incremental_score_prune(goal_ref const & g, func_decl * fd, const mpz & new_value) {
-            m_stats.m_incr_evals++;
-            if (m_evaluator.update_prune(fd, new_value))
-#if _CACHE_TOP_SCORE_
-                return (m_tracker.get_top_sum() / g->size());
-#else
-                return top_score(g);
-#endif
-            else
-                return 0.0;
-        }
-#endif
-
-        // checks whether the score outcome of a given move is better than the previous score
-        bool what_if(goal_ref const & g, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-
-            #ifdef Z3DEBUG
-            mpz old_value;
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-            #endif
-
-#if _EARLY_PRUNE_
-            double r = incremental_score_prune(g, fd, temp);
-#else
-            double r = incremental_score(g, fd, temp);
-#endif   
-            #ifdef Z3DEBUG
-            TRACE("sls_whatif", tout << "WHAT IF " << fd->get_name() << " WERE " << m_mpz_manager.to_string(temp) << 
-                                        " --> " << r << std::endl; );
-        
-            m_mpz_manager.del(old_value);
-            #endif
-
-//            if (r >= best_score) {
-            if (r > best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // same as what_if, but only applied to the score of a specific atom, not the total score
-        bool what_if_local(expr * e, func_decl * fd, const unsigned & fd_inx, const mpz & temp, 
-                        double & best_score, unsigned & best_const, mpz & best_value) {
-            m_evaluator.update(fd, temp);
-            double r = m_tracker.get_score(e);
-            if (r >= best_score) {
-                best_score = r;
-                best_const = fd_inx;            
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        void mk_add(unsigned bv_sz, const mpz & old_value, mpz & add_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.add(old_value, add_value, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-
-        }
-
-        // Andreas: do we really need all those temporary mpzs?
-        void mk_mul2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            mpz temp, mask, mask2;
-            m_mpz_manager.mul(old_value, m_two, temp);
-            m_mpz_manager.set(mask, m_powers(bv_sz));
-            m_mpz_manager.bitwise_not(bv_sz, mask, mask2);
-            m_mpz_manager.bitwise_and(temp, mask2, result);
-            m_mpz_manager.del(temp);
-            m_mpz_manager.del(mask);
-            m_mpz_manager.del(mask2);
-        }
-
-        void mk_div2(unsigned bv_sz, const mpz & old_value, mpz & result) {
-            m_mpz_manager.div(old_value, m_two, result);
-        }
-
-        void mk_inc(unsigned bv_sz, const mpz & old_value, mpz & incremented) {
-            unsigned shift;        
-            m_mpz_manager.add(old_value, m_one, incremented);
-            if (m_mpz_manager.is_power_of_two(incremented, shift) && shift == bv_sz)
-                m_mpz_manager.set(incremented, m_zero);
-        }
-
-        void mk_dec(unsigned bv_sz, const mpz & old_value, mpz & decremented) {
-            if (m_mpz_manager.is_zero(old_value)) {
-                m_mpz_manager.set(decremented, m_powers(bv_sz));
-                m_mpz_manager.dec(decremented);
-            }
-            else
-                m_mpz_manager.sub(old_value, m_one, decremented);
-        }
-
-        void mk_inv(unsigned bv_sz, const mpz & old_value, mpz & inverted) {
-            m_mpz_manager.bitwise_not(bv_sz, old_value, inverted);
-        }
-
-        void mk_flip(sort * s, const mpz & old_value, unsigned bit, mpz & flipped) {
-            m_mpz_manager.set(flipped, m_zero);
-
-            if (m_bv_util.is_bv_sort(s)) {
-                mpz mask;
-                m_mpz_manager.set(mask, m_powers(bit));
-                m_mpz_manager.bitwise_xor(old_value, mask, flipped);
-                m_mpz_manager.del(mask);
-            }
-            else if (m_manager.is_bool(s))
-                m_mpz_manager.set(flipped, (m_mpz_manager.is_zero(old_value)) ? m_one : m_zero);
-            else
-                NOT_IMPLEMENTED_YET();
-        }
-
-        void mk_random_move(ptr_vector<func_decl> & unsat_constants)
-        {
-            unsigned rnd_mv = 0;
-            unsigned ucc = unsat_constants.size(); 
-            unsigned rc = (m_tracker.get_random_uint((ucc < 16) ? 4 : (ucc < 256) ? 8 : (ucc < 4096) ? 12 : (ucc < 65536) ? 16 : 32)) % ucc;
-            func_decl * fd = unsat_constants[rc];
-
-            mpz new_value;
-
-            sort * srt = fd->get_range();
-            if (m_manager.is_bool(srt))
-                m_mpz_manager.set(new_value, (m_mpz_manager.is_zero(m_tracker.get_value(fd))) ? m_one : m_zero);
-            else
-            {
-#if _USE_ADDSUB_
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv=2;
-                if (m_mpz_manager.is_one(m_tracker.get_random_bool())) rnd_mv++;
-                move_type mt = (move_type) rnd_mv;
-
-                // inversion doesn't make sense, let's do a flip instead.
-                if (mt == MV_INV) mt = MV_FLIP;
-#else
-                mt = MV_FLIP;
-#endif
-                unsigned bit = 0;
-
-                switch (mt)
-                {
-                    case MV_FLIP: {
-                    unsigned bv_sz = m_bv_util.get_bv_size(srt);
-                    bit = (m_tracker.get_random_uint((bv_sz < 16) ? 4 : (bv_sz < 256) ? 8 : (bv_sz < 4096) ? 12 : (bv_sz < 65536) ? 16 : 32)) % bv_sz;
-                    mk_flip(fd->get_range(), m_tracker.get_value(fd), bit, new_value);
-                    break;
-                }
-                case MV_INC: 
-                    mk_inc(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_DEC: 
-                    mk_dec(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                case MV_INV:
-                    mk_inv(m_bv_util.get_bv_size(fd->get_range()), m_tracker.get_value(fd), new_value);
-                    break;
-                default:
-                    NOT_IMPLEMENTED_YET();
-                }
-
-                TRACE("sls", tout << "Randomization candidates: ";
-                             for (unsigned i = 0; i < unsat_constants.size(); i++)
-                                 tout << unsat_constants[i]->get_name() << ", ";
-                             tout << std::endl;
-                             tout << "Random move: ";
-                             switch (mt) {
-                             case MV_FLIP: tout << "Flip #" << bit << " in " << fd->get_name() << std::endl; break;
-                             case MV_INC: tout << "+1 for " << fd->get_name() << std::endl; break;
-                             case MV_DEC: tout << "-1 for " << fd->get_name() << std::endl; break;
-                             case MV_INV: tout << "NEG for " << fd->get_name() << std::endl; break;
-                             }
-                             tout << "Locally randomized model: " << std::endl; m_tracker.show_model(tout); );            
-            }
-
-            m_evaluator.update(fd, new_value);            
-            m_mpz_manager.del(new_value);
-        }
-
-        void mk_random_move(goal_ref const & g) {
-            mk_random_move(m_tracker.get_unsat_constants(g, m_stats.m_moves));                
-        }
-
-        // will use VNS to ignore some possible moves and increase the flips per second
-        double find_best_move_vns(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz, max_bv_sz = 0;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                if (max_bv_sz < bv_sz) max_bv_sz = bv_sz;
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-                    // try to flip lsb
-                    mk_flip(srt, old_value, 0, temp);                
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = 0;
-                        move = MV_FLIP;
-                    }
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-
-            // we can either check the condition once in the beginning or check it repeatedly after every bit
-#if _VNS_ == 1
-            for (unsigned j = 1; j < max_bv_sz && new_score <= score; j++)
-#else
-            if (new_score <= score)
-            for (unsigned j = 1; j < max_bv_sz && new_score < 1.0; j++)
-#endif
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // What would happen if we flipped bit #j ?                
-                if (j < bv_sz)
-                {
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                SASSERT(check == score);
-            }
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // finds the move that increased score the most. returns best_const = -1, if no increasing move exists.
-        double find_best_move(goal_ref const & g, ptr_vector<func_decl> & to_evaluate, double score, 
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-#if _USE_MUL3_ || _USE_UNARY_MINUS_
-            mpz temp2;
-#endif
-            unsigned bv_sz;
-            double new_score = score;
-
-            for (unsigned i = 0; i < to_evaluate.size() && new_score < 1.0 ; i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-#if _SKIP_BITS_
-                for (unsigned j = (i + m_stats.m_moves) % (_SKIP_BITS_ + 1); j < bv_sz && new_score < 1.0; j+=(_SKIP_BITS_ + 1)) {
-#else
-                for (unsigned j = 0; j < bv_sz && new_score < 1.0; j++) {
-#endif
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-#if _USE_ADDSUB_
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-#endif
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-
-#if _USE_UNARY_MINUS_
-                    mk_inc(bv_sz, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_UMIN;
-#endif
-
-#if _USE_MUL2DIV2_
-                    // try multiplication by 2
-                    mk_mul2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_MUL2;
-
-#if _USE_MUL3_
-                    // try multiplication by 3
-                    mk_add(bv_sz, old_value, temp, temp2);
-                    if (what_if(g, fd, i, temp2, new_score, best_const, best_value))
-                        move = MV_MUL3;
-#endif
-
-                    // try division by 2
-                    mk_div2(bv_sz, old_value, temp);
-                    if (what_if(g, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_DIV2;
-#endif
-                }
-
-                // reset to what it was before
-                double check = incremental_score(g, fd, old_value);
-                // Andreas: does not hold anymore now that we use top level score caching
-                //SASSERT(check == score);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-#if _USE_MUL3_
-            m_mpz_manager.del(temp2);
-#endif
-            return new_score;
-        }        
-
-        // same as find_best_move but only considers the score of the current expression instead of the overall score
-        double find_best_move_local(expr * e, ptr_vector<func_decl> & to_evaluate,
-                              unsigned & best_const, mpz & best_value, unsigned & new_bit, move_type & move) {
-            mpz old_value, temp;
-            unsigned bv_sz;
-            double new_score = m_tracker.get_score(e);
-            // Andreas: tie breaking not implemented yet
-            // double tie_score = top_score(g);
-            for (unsigned i = 0; i < to_evaluate.size(); i++) {
-                func_decl * fd = to_evaluate[i];
-                sort * srt = fd->get_range();
-                bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-                m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-                // first try to flip every bit
-                for (unsigned j = 0; j < bv_sz; j++) {
-                    // What would happen if we flipped bit #i ?                
-                    mk_flip(srt, old_value, j, temp);                
-
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value)) {
-                        new_bit = j;
-                        move = MV_FLIP;
-                    }
-                }
-
-                if (m_bv_util.is_bv_sort(srt) && bv_sz > 1) {
-                    if (!m_mpz_manager.is_even(old_value)) { 
-                        // for odd values, try +1
-                        mk_inc(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_INC;
-                    }
-                    else { 
-                        // for even values, try -1
-                        mk_dec(bv_sz, old_value, temp);
-                        if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                            move = MV_DEC;
-                    }
-
-                    // try inverting
-                    mk_inv(bv_sz, old_value, temp);
-                    if (what_if_local(e, fd, i, temp, new_score, best_const, best_value))
-                        move = MV_INV;
-                }
-
-                // reset to what it was before
-                m_evaluator.update(fd, old_value);
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-            return new_score;
-        }        
-
-        // first try of intensification ... does not seem to be efficient
-        bool handle_plateau(goal_ref const & g)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned pos = m_stats.m_moves % sz;
-#else
-            unsigned pos = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, pos);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-            {
-                m_tracker.get_value(to_evaluate[i]);
-                m_old_values.push_back( & m_tracker.get_value(to_evaluate[i]));
-            }            
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            for (unsigned i = 0; i < _INTENSIFICATION_TRIES_; i++)
-            {
-                // Andreas: Could be extended to use (best) score but this is computationally more expensive.
-                find_best_move_local(q, to_evaluate, new_const, new_value, new_bit, move);
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    // Andreas: Actually this should never happen.
-                    NOT_IMPLEMENTED_YET();
-                } else {
-                    m_stats.m_moves++;
-                    func_decl * fd = to_evaluate[new_const];
-
-                    switch (move) {
-                    case MV_FLIP: m_stats.m_flips++; break;
-                    case MV_INC: m_stats.m_incs++; break;
-                    case MV_DEC: m_stats.m_decs++; break;
-                    case MV_INV: m_stats.m_invs++; break;
-                    case MV_UMIN: m_stats.m_umins++; break;
-                    case MV_MUL2: m_stats.m_mul2s++; break;
-                    case MV_MUL3: m_stats.m_mul3s++; break;
-                    case MV_DIV2: m_stats.m_div2s++; break;
-                    }
-                    
-                    m_evaluator.update(fd, new_value);
-                }
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            for (unsigned i = 0; i < to_evaluate.size(); i++)
-                m_tracker.set_value(to_evaluate[i], * m_old_values[i]);
-
-            m_old_values.reset();
-
-            return 0;
-        }
-
-        // what_if version needed in the context of 2nd intensification try, combining local and global score
-        bool what_if(goal_ref const & g, expr * e, func_decl * fd, const mpz & temp, 
-                        double & best_score, mpz & best_value, unsigned i) {
-        
-            double global_score = incremental_score(g, fd, temp);
-            double local_score = m_tracker.get_score(e);
-            double new_score = i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_;
-
-            if (new_score >= best_score) {
-                best_score = new_score;
-                m_mpz_manager.set(best_value, temp);
-                return true;
-            }
-
-            return false;
-        }
-
-        // find_best_move version needed in the context of 2nd intensification try
-        double find_best_move_local(goal_ref const & g, expr * e, func_decl * fd, mpz & best_value, unsigned i)
-        {
-            mpz old_value, temp;
-            double best_score = 0;
-
-            sort * srt = fd->get_range();
-            unsigned bv_sz = (m_manager.is_bool(srt)) ? 1 : m_bv_util.get_bv_size(srt);
-            m_mpz_manager.set(old_value, m_tracker.get_value(fd));
-
-            for (unsigned j = 0; j < bv_sz && best_score < 1.0; j++) {
-                mk_flip(srt, old_value, j, temp);                
-                what_if(g, e, fd, temp, best_score, best_value, i); 
-            }
-
-            m_mpz_manager.del(old_value);
-            m_mpz_manager.del(temp);
-
-            return best_score;
-        }        
-
-        // second try to use intensification ... also not very effective
-        bool handle_plateau(goal_ref const & g, double old_score)
-        {
-            unsigned sz = g->size();
-#if _BFS_
-            unsigned new_const = m_stats.m_moves % sz;
-#else
-            unsigned new_const = m_tracker.get_random_uint(16) % sz;
-#endif
-            expr * e = m_tracker.get_unsat_assertion(g, sz, new_const);
-            if (!e)
-                return 0;
-
-            expr * q = m_tracker.get_unsat_expression(e);
-            ptr_vector<func_decl> & to_evaluate = m_tracker.get_constants(q);
-
-            new_const = m_tracker.get_random_uint(16) % to_evaluate.size();
-            func_decl * fd = to_evaluate[new_const];
-
-            mpz new_value;
-            //m_mpz_manager.set(new_value, m_tracker.get_value(fd));
-            unsigned new_bit = 0;        
-            double global_score = old_score, local_score = m_tracker.get_score(q), new_score = old_score;
-            
-            for (unsigned i = 1; i <= _INTENSIFICATION_TRIES_; i++)
-            {
-                new_score = find_best_move_local(g, q, fd, new_value, i);
-
-                m_stats.m_moves++;
-                m_stats.m_flips++;
-
-                global_score = incremental_score(g, fd, new_value);
-                local_score = m_tracker.get_score(q);
-
-                SASSERT(new_score == i * local_score / _INTENSIFICATION_TRIES_ + (_INTENSIFICATION_TRIES_ - i) * global_score / _INTENSIFICATION_TRIES_);
-
-                if (m_mpz_manager.is_one(m_tracker.get_value(q)))
-                    return 1;
-            }
-
-            return 0;
-        }
-
-        // main search loop
-        lbool search(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            unsigned plateau_cnt = 0;
-
-            score = rescore(g);
-            unsigned sz = g->size();
-#if _PERC_STICKY_
-            expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-
-#if _RESTARTS_ == 1
-            while (check_restart(m_stats.m_moves) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 2
-            while (check_restart(plateau_cnt) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#elif _RESTARTS_ == 3
-            while (check_restart((unsigned)m_stats.m_stopwatch.get_current_seconds()) && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#endif
-                checkpoint();
-                m_stats.m_moves++;
-
-#if _UCT_FORGET_
-                if (m_stats.m_moves % _UCT_FORGET_ == 0)
-                    m_tracker.uct_forget(g);
-#endif
-
-#if _REAL_RS_ || _REAL_PBFS_
-                //m_tracker.debug_real(g, m_stats.m_moves);
-#endif
-
-#if _FOCUS_
-#if _PERC_STICKY_
-                if (m_tracker.get_random_uint(16) % 100 >= _PERC_STICKY_ || m_mpz_manager.eq(m_tracker.get_value(e), m_one))
-                e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#else
-                expr * e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-#endif
-                if (!e)
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-                ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants_gsat(g, sz);
-                if (!to_evaluate.size())
-                {
-                    res = l_true;
-                    goto bailout;
-                }
-#endif
-
-#if _TYPE_RSTEP_
-                if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                {
-#if _TYPE_RSTEP_ == 1
-                    m_evaluator.randomize_local(to_evaluate);
-#elif _TYPE_RSTEP_ == 2
-                    mk_random_move(to_evaluate);
-#endif
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                }
-                continue;
-#endif
-
-#if _WEIGHT_DIST_ == 4
-                m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif       
-                old_score = score;
-                new_const = (unsigned)-1;
-
-#if _VNS_
-                score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-
-                if (new_const == static_cast<unsigned>(-1)) {
-                    score = old_score;
-                    plateau_cnt++;
-#if _INTENSIFICATION_
-                    handle_plateau(g, score);
-                    //handle_plateau(g);
-                    //e = m_tracker.get_unsat_assertion(g, m_stats.m_moves);    
-                    //to_evaluate = m_tracker.get_unsat_constants_walksat(e);
-#else
-#if _PERC_PLATEAU_MOVES_
-                    if (m_tracker.get_random_uint(8) % 100 < _PERC_PLATEAU_MOVES_)
-                        mk_random_move(to_evaluate);
-                    else
-#endif
-#if _REPICK_
-                    m_evaluator.randomize_local(g, m_stats.m_moves);
-#else
-                    m_evaluator.randomize_local(to_evaluate);
-#endif
-#endif
-
-#if _CACHE_TOP_SCORE_
-                    score = m_tracker.get_top_sum() / g->size();
-#else
-                    score = top_score(g);
-#endif
-                } else {
-                    func_decl * fd = to_evaluate[new_const];              
-#if _REAL_RS_ || _REAL_PBFS_
-                    score = serious_score(g, fd, new_value);
-#else
-                    score = incremental_score(g, fd, new_value);    
-#endif
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        // main search loop
-        lbool search_old(goal_ref const & g) {        
-            lbool res = l_undef;
-            double score = 0.0, old_score = 0.0;
-            unsigned new_const = (unsigned)-1, new_bit = 0;        
-            mpz new_value;
-            move_type move;
-            
-            score = rescore(g);
-            TRACE("sls", tout << "Starting search, initial score   = " << std::setprecision(32) << score << std::endl;
-                         tout << "Score distribution:"; 
-                         for (unsigned i = 0; i < g->size(); i++)
-                             tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                         tout << " TOP: " << score << std::endl; ); 
-        
-            unsigned plateau_cnt = 0;
-
-            // Andreas: Why do we only allow so few plateaus?
-#if _RESTARTS_
-            while (m_stats.m_stopwatch.get_current_seconds() < 200 * (m_stats.m_restarts + 1) * 0.2) {
-            //while (plateau_cnt < m_plateau_limit && m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_) {                
-#else
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && (_RESTARTS_ == 0 || m_stats.m_moves < _RESTARTS_)) {                
-#endif
-                do {
-                    checkpoint();
-
-#if _WEIGHT_DIST_ == 4
-                    m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-            
-#if _TYPE_RSTEP_
-                    if (m_tracker.get_random_uint(16) % 1000 < _PERM_RSTEP_)
-                    {
-#if _TYPE_RSTEP_ == 1
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#elif _TYPE_RSTEP_ == 2
-                        mk_random_move(g);
-#endif
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                            } else
-                                TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                        }
-                    }
-#endif
-                    old_score = score;
-                    new_const = (unsigned)-1;
-                        
-                    ptr_vector<func_decl> & to_evaluate = m_tracker.get_unsat_constants(g, m_stats.m_moves);
-                    if (!to_evaluate.size())
-                    {
-                        res = l_true;
-                        goto bailout;
-                    }
-                    TRACE("sls_constants", tout << "Evaluating these constants: " << std::endl;
-                                            for (unsigned i = 0 ; i < to_evaluate.size(); i++)
-                                                tout << to_evaluate[i]->get_name() << std::endl; );
-
-#if _VNS_
-                    score = find_best_move_vns(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#else
-                    score = find_best_move(g, to_evaluate, score, new_const, new_value, new_bit, move);
-#endif
-                    if (new_const == static_cast<unsigned>(-1)) {
-                        TRACE("sls", tout << "Local maximum reached; unsatisfied constraints: " << std::endl; 
-                                        for (unsigned i = 0; i < g->size(); i++) {
-                                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                                tout << mk_ismt2_pp(g->form(i), m_manager) << std::endl;
-                                        });
-
-                        TRACE("sls_max", m_tracker.show_model(tout);
-                                        tout << "Scores: " << std::endl;
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << mk_ismt2_pp(g->form(i), m_manager) << " ---> " << 
-                                            m_tracker.get_score(g->form(i)) << std::endl; );
-                        // Andreas: If new_const == -1, shouldn't score = old_score anyway?
-                        score = old_score;
-                    }
-                    else {
-                        // Andreas: Why does randomizing not count as a move? (Now it does.)
-                        m_stats.m_moves++;
-                        func_decl * fd = to_evaluate[new_const];
-
-                        TRACE("sls", tout << "Setting " << fd->get_name() << " to " << m_mpz_manager.to_string(new_value) << " (Move: ";
-                                        switch (move) {
-                                        case MV_FLIP:  
-                                            tout << "Flip";
-                                            if (!m_manager.is_bool(fd->get_range())) tout << " #" << new_bit;
-                                            break;
-                                        case MV_INC: 
-                                            tout << "+1";
-                                            break;
-                                        case MV_DEC: 
-                                            tout << "-1";
-                                            break;
-                                        case MV_INV: 
-                                            tout << "NEG";
-                                            break;
-                                        };                                        
-                                        tout << ") ; new score = " << std::setprecision(32) << score << std::endl; );
-
-                        switch (move) {
-                        case MV_FLIP: m_stats.m_flips++; break;
-                        case MV_INC: m_stats.m_incs++; break;
-                        case MV_DEC: m_stats.m_decs++; break;
-                        case MV_INV: m_stats.m_invs++; break;
-                        case MV_UMIN: m_stats.m_umins++; break;
-                        case MV_MUL2: m_stats.m_mul2s++; break;
-                        case MV_MUL3: m_stats.m_mul3s++; break;
-                        case MV_DIV2: m_stats.m_div2s++; break;
-                        }
-                    
-#if _REAL_RS_ || _REAL_PBFS_
-                        score = serious_score(g, fd, new_value);
-#else
-                        score = incremental_score(g, fd, new_value);    
-#endif
-
-                        TRACE("sls", tout << "Score distribution:"; 
-                                        for (unsigned i = 0; i < g->size(); i++)
-                                            tout << " " << std::setprecision(3) << m_tracker.get_score(g->form(i));
-                                        tout << " TOP: " << score << std::endl; );                        
-                    }
-
-                    if (score >= 0.99999) {
-//                    if (score >= 1.0) {
-                        // score could theoretically be imprecise.
-                        // Andreas: it seems using top level score caching can make the score unprecise also in the other direction!
-                        bool all_true = true;
-                        for (unsigned i = 0; i < g->size() && all_true; i++)
-                            if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                all_true=false;
-                        if (all_true) {
-                            res = l_true; // sat
-                            goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                    /*
-                    if (m_stats.m_moves % 100 == 0)
-                    {
-                        verbose_stream() << "(" << std::fixed << std::setprecision(10) << score << ")" << std::endl;
-                        verbose_stream() << "(" << std::fixed << std::setprecision(2) << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-                    }*/
-                }
-                while (score > old_score && res == l_undef);                
-                
-                // Andreas: Why do you check for old_score? This should always be equal due to the loop invariant.
-                if (score != old_score) {
-                    report_tactic_progress("This should not happen I guess.", plateau_cnt);
-                    plateau_cnt = 0;
-                } else {
-                    m_stats.m_moves++;
-                    plateau_cnt++;
-                    //report_tactic_progress("Plateau.", plateau_cnt);
-                    // Andreas: Right now, a useless assignment is created in case of a restart. But we don't want to use restarts anyway.
-                    //if (plateau_cnt < m_plateau_limit) {
-                        TRACE("sls", tout << "In a plateau (" << plateau_cnt << "/" << m_plateau_limit << "); randomizing locally." << std::endl; );
-#if _INTENSIFICATION_
-                        handle_plateau(g, score);
-                        //handle_plateau(g);
-#else
-                        m_evaluator.randomize_local(g, m_stats.m_moves);
-#endif
-                        //mk_random_move(g);
-                        score = top_score(g);
-
-                        if (score >= 1.0) {
-                            bool all_true = true;
-                            for (unsigned i = 0; i < g->size() && all_true; i++)
-                                if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                                    all_true=false;
-                            if (all_true) {
-                                res = l_true; // sat
-                                goto bailout;
-                        } else
-                            TRACE("sls", tout << "Imprecise 1.0 score" << std::endl;);
-                    }
-                }
-            }
-
-            bailout:
-            m_mpz_manager.del(new_value);
-
-            return res;
-        }    
-
-        void operator()(goal_ref const & g, model_converter_ref & mc) {
-            if (g->inconsistent()) {
-                mc = 0;
-                return;
-            }
-
-            verbose_stream() << "_BFS_ " << _BFS_ << std::endl;
-            verbose_stream() << "_FOCUS_ " << _FOCUS_ << std::endl;
-            verbose_stream() << "_DIRTY_UP_ " << _DIRTY_UP_ << std::endl;
-            verbose_stream() << "_PERC_STICKY_ " << _PERC_STICKY_ << std::endl;
-            verbose_stream() << "_RESTARTS_ " << _RESTARTS_ << std::endl;
-            verbose_stream() << "_RESTART_LIMIT_ " << _RESTART_LIMIT_ << std::endl;
-            verbose_stream() << "_RESTART_INIT_ " << _RESTART_INIT_ << std::endl;
-            verbose_stream() << "_RESTART_SCHEME_ " << _RESTART_SCHEME_ << std::endl;
-            verbose_stream() << "_RESTART_CONST_ARMIN_ " << std::fixed << std::setprecision(2) << _RESTART_CONST_ARMIN_ << std::endl;
-            verbose_stream() << "_TIMELIMIT_ " << _TIMELIMIT_ << std::endl;
-            verbose_stream() << "_SCORE_AND_AVG_ " << _SCORE_AND_AVG_ << std::endl;
-            verbose_stream() << "_SCORE_OR_MUL_ " << _SCORE_OR_MUL_ << std::endl;
-            verbose_stream() << "_VNS_ " << _VNS_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_ " << _WEIGHT_DIST_ << std::endl;
-            verbose_stream() << "_WEIGHT_DIST_FACTOR_ " << std::fixed << std::setprecision(2) << _WEIGHT_DIST_FACTOR_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_ " << _INTENSIFICATION_ << std::endl;
-            verbose_stream() << "_INTENSIFICATION_TRIES_ " << _INTENSIFICATION_TRIES_ << std::endl;
-            verbose_stream() << "_PERC_PLATEAU_MOVES_ " << _PERC_PLATEAU_MOVES_ << std::endl;
-            verbose_stream() << "_REPICK_ " << _REPICK_ << std::endl;
-            verbose_stream() << "_UCT_ " << _UCT_ << std::endl;
-            verbose_stream() << "_UCT_CONSTANT_ " << std::fixed << std::setprecision(2) << _UCT_CONSTANT_ << std::endl;
-            verbose_stream() << "_UCT_RESET_ " << _UCT_RESET_ << std::endl;
-            verbose_stream() << "_UCT_INIT_ " << _UCT_INIT_ << std::endl;
-            verbose_stream() << "_UCT_FORGET_ " << _UCT_FORGET_ << std::endl;
-            verbose_stream() << "_UCT_FORGET_FACTOR_ " << std::fixed << std::setprecision(2) << _UCT_FORGET_FACTOR_ << std::endl;
-            verbose_stream() << "_PROBABILISTIC_UCT_ " << _PROBABILISTIC_UCT_ << std::endl;
-            verbose_stream() << "_UCT_EPS_ " << std::fixed << std::setprecision(4) << _UCT_EPS_ << std::endl;
-            verbose_stream() << "_USE_ADDSUB_ " << _USE_ADDSUB_ << std::endl;
-            verbose_stream() << "_USE_MUL2DIV2_ " << _USE_MUL2DIV2_ << std::endl;
-            verbose_stream() << "_USE_MUL3_ " << _USE_MUL3_ << std::endl;
-            verbose_stream() << "_USE_UNARY_MINUS_ " << _USE_UNARY_MINUS_ << std::endl;
-            verbose_stream() << "_UNIFORM_RANDOM_ " << _UNIFORM_RANDOM_ << std::endl;
-            verbose_stream() << "_REAL_RS_ " << _REAL_RS_ << std::endl;
-            verbose_stream() << "_REAL_PBFS_ " << _REAL_PBFS_ << std::endl;
-            verbose_stream() << "_SKIP_BITS_ " << _SKIP_BITS_ << std::endl;
-            verbose_stream() << "_PERC_CHANGE_ " << _PERC_CHANGE_ << std::endl;
-            verbose_stream() << "_TYPE_RSTEP_ " << _TYPE_RSTEP_ << std::endl;
-            verbose_stream() << "_PERM_RSTEP_ " << _PERM_RSTEP_ << std::endl;
-            verbose_stream() << "_EARLY_PRUNE_ " << _EARLY_PRUNE_ << std::endl;
-            verbose_stream() << "_CACHE_TOP_SCORE_ " << _CACHE_TOP_SCORE_ << std::endl;
-            
-#if _WEIGHT_DIST_ == 4
-            m_tracker.set_weight_dist_factor(m_stats.m_stopwatch.get_current_seconds() / _TIMELIMIT_);
-#endif
-#if _WEIGHT_TOGGLE_
-            m_tracker.set_weight_dist_factor(_WEIGHT_DIST_FACTOR_);
-#endif
-            m_tracker.initialize(g);
-            lbool res = l_undef;
-        
-            m_restart_limit = _RESTART_LIMIT_;
-
-            do {
-                checkpoint();
-
-                report_tactic_progress("Searching... restarts left:", m_max_restarts - m_stats.m_restarts);
-                res = search(g);
-
-                if (res == l_undef)
-                {
-#if _RESTART_INIT_
-                    m_tracker.randomize(g);
-#else
-                    m_tracker.reset(g);
-#endif
-                }
-            }
-            while (m_stats.m_stopwatch.get_current_seconds() < _TIMELIMIT_ && res != l_true && m_stats.m_restarts++ < m_max_restarts);
-        
-            verbose_stream() << "(restarts: " << m_stats.m_restarts << " flips: " << m_stats.m_moves << " time: " << std::fixed << std::setprecision(2) << m_stats.m_stopwatch.get_current_seconds() << " fps: " << (m_stats.m_moves / m_stats.m_stopwatch.get_current_seconds()) << ")" << std::endl;
-
-            if (res == l_true) {    
-                report_tactic_progress("Number of flips:", m_stats.m_moves);
-                for (unsigned i = 0; i < g->size(); i++)
-                    if (!m_mpz_manager.is_one(m_tracker.get_value(g->form(i))))
-                    {
-                        verbose_stream() << "Terminated before all assertions were SAT!" << std::endl;
-                        NOT_IMPLEMENTED_YET(); 
-                    }
-
-                if (m_produce_models) {
-                    model_ref mdl = m_tracker.get_model();
-                    mc = model2model_converter(mdl.get());
-                    TRACE("sls_model", mc->display(tout); );
-                }
-                g->reset();
-            }
-            else
-                mc = 0;
-        }
-    };
-    
+class sls_tactic : public tactic {    
     ast_manager    & m;
     params_ref       m_params;
-    imp            * m_imp;
-    stats            m_stats;
+    sls_engine     * m_engine;
 
 public:
     sls_tactic(ast_manager & _m, params_ref const & p):
         m(_m),
         m_params(p) {
-        m_imp = alloc(imp, m, p, m_stats);
+        m_engine = alloc(sls_engine, m, p);
     }
 
     virtual tactic * translate(ast_manager & m) {
@@ -1395,16 +47,16 @@ public:
     }
 
     virtual ~sls_tactic() {
-        dealloc(m_imp);
+        dealloc(m_engine);
     }
 
     virtual void updt_params(params_ref const & p) {
         m_params = p;
-        m_imp->updt_params(p);
+        m_engine->updt_params(p);
     }
 
     virtual void collect_param_descrs(param_descrs & r) {
-        imp::collect_param_descrs(r);
+        sls_params::collect_param_descrs(r);
     }
     
     virtual void operator()(goal_ref const & g, 
@@ -1412,14 +64,13 @@ public:
                             model_converter_ref & mc, 
                             proof_converter_ref & pc,
                             expr_dependency_ref & core) {
-        SASSERT(g->is_well_sorted());
-        m_imp->m_produce_models = g->models_enabled();        
+        SASSERT(g->is_well_sorted());        
         mc = 0; pc = 0; core = 0; result.reset();
         
         TRACE("sls", g->display(tout););
         tactic_report report("sls", *g);
         
-        m_imp->operator()(g, mc);
+        m_engine->operator()(g, mc);
 
         g->inc_depth();
         result.push_back(g.get());
@@ -1428,40 +79,36 @@ public:
     }
 
     virtual void cleanup() {        
-        imp * d = m_imp;
+        sls_engine * d = alloc(sls_engine, m, m_params);
         #pragma omp critical (tactic_cancel)
         {
-            d = m_imp;
+            std::swap(d, m_engine);
         }
         dealloc(d);
-        d = alloc(imp, m, m_params, m_stats);
-        #pragma omp critical (tactic_cancel) 
-        {
-            m_imp = d;
-        }
     }
     
     virtual void collect_statistics(statistics & st) const {
-        double seconds = m_stats.m_stopwatch.get_current_seconds();            
-        st.update("sls restarts", m_stats.m_restarts);
-        st.update("sls full evals", m_stats.m_full_evals);
-        st.update("sls incr evals", m_stats.m_incr_evals);
-        st.update("sls incr evals/sec", m_stats.m_incr_evals/ seconds);
-        st.update("sls FLIP moves", m_stats.m_flips);    
-        st.update("sls INC moves", m_stats.m_incs);
-        st.update("sls DEC moves", m_stats.m_decs);
-        st.update("sls INV moves", m_stats.m_invs);
-        st.update("sls moves", m_stats.m_moves);
-        st.update("sls moves/sec", m_stats.m_moves / seconds);
+        sls_engine::stats const & stats = m_engine->get_stats();
+        double seconds = stats.m_stopwatch.get_current_seconds();            
+        st.update("sls restarts", stats.m_restarts);
+        st.update("sls full evals", stats.m_full_evals);
+        st.update("sls incr evals", stats.m_incr_evals);
+        st.update("sls incr evals/sec", stats.m_incr_evals / seconds);
+        st.update("sls FLIP moves", stats.m_flips);
+        st.update("sls INC moves", stats.m_incs);
+        st.update("sls DEC moves", stats.m_decs);
+        st.update("sls INV moves", stats.m_invs);
+        st.update("sls moves", stats.m_moves);
+        st.update("sls moves/sec", stats.m_moves / seconds);
     }
 
     virtual void reset_statistics() {
-        m_stats.reset();
+        m_engine->reset_statistics();
     }
 
     virtual void set_cancel(bool f) {
-        if (m_imp)
-            m_imp->set_cancel(f);
+        if (m_engine)
+            m_engine->set_cancel(f);
     }
 };
 

From 168c3eb363e89b245cd4d36b3a7e744b3e979748 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Fri, 19 Dec 2014 12:32:57 +0000
Subject: [PATCH 096/108] BV-SLS optimization

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 14 +++++++++++---
 1 file changed, 11 insertions(+), 3 deletions(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 73355197a..89ef57871 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -89,6 +89,7 @@ private:
     unsigned              m_track_unsat;
     obj_map<expr, unsigned> m_weights;
     double				  m_top_sum;
+    obj_hashtable<expr>   m_temp_seen;
 
 public:    
     sls_tracker(ast_manager & m, bv_util & bvu, unsynch_mpz_manager & mm, powers & p) :
@@ -440,6 +441,7 @@ public:
             }
         }
 
+        m_temp_seen.reset();
         for (unsigned i = 0; i < sz; i++)
         {
             expr * e = as[i];
@@ -630,7 +632,14 @@ public:
                 app * a = to_app(n);
                 expr * const * args = a->get_args();
                 for (unsigned i = 0; i < a->get_num_args(); i++)
-                    setup_occs(args[i]);
+                {
+                    expr * child = args[i];
+                    if (!m_temp_seen.contains(child))
+                    {
+                        setup_occs(child, false);
+                        m_temp_seen.insert(child);
+                    }
+                }
             }
             else if (m_manager.is_not(n))
             {
@@ -638,8 +647,7 @@ public:
                 app * a = to_app(n);
                 SASSERT(a->get_num_args() == 1);
                 expr * child = a->get_arg(0);
-                if (m_manager.is_and(child) || m_manager.is_or(child))
-                    NOT_IMPLEMENTED_YET();
+                SASSERT(!m_manager.is_and(child) && !m_manager.is_or(child));
                 setup_occs(child, true);
             }
             else

From 916ef815fabe999205a858cf27063a859b1b3dd9 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 12 Jan 2015 15:59:20 +0000
Subject: [PATCH 097/108] Disabled BV-SLS as default tactic in anticipation for
 integration with the unstable branch.

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/portfolio/default_tactic.cpp | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 53da9a159..5a5cbcf94 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -32,8 +32,7 @@ Notes:
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),  mk_qfbv_sls_tactic(m),
-  //                                      cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
+                                        cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),

From 58bf80f1138ffe356e603a76ebff8f8c8de6686b Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 12 Jan 2015 17:03:56 +0000
Subject: [PATCH 098/108] Cosmetics

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/smtlogics/qfbv_tactic.cpp | 2 --
 1 file changed, 2 deletions(-)

diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp
index a7870176d..3b4da2f2d 100644
--- a/src/tactic/smtlogics/qfbv_tactic.cpp
+++ b/src/tactic/smtlogics/qfbv_tactic.cpp
@@ -28,8 +28,6 @@ Notes:
 #include"bv_size_reduction_tactic.h"
 #include"aig_tactic.h"
 #include"sat_tactic.h"
-//#include"nnf_tactic.h"
-//#include"sls_tactic.h"
 
 #define MEMLIMIT 300
 

From f1a00da401ccd42155e3753bc83320e81b89b1bb Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 12 Jan 2015 17:43:56 +0000
Subject: [PATCH 099/108] BV-SLS Cosmetics

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/sat/tactic/sat_tactic.cpp                 |  2 --
 src/tactic/portfolio/default_tactic.cpp       |  1 -
 src/tactic/portfolio/smt_strategic_solver.cpp |  5 +---
 src/tactic/smtlogics/qfbv_tactic.cpp          | 26 -------------------
 4 files changed, 1 insertion(+), 33 deletions(-)

diff --git a/src/sat/tactic/sat_tactic.cpp b/src/sat/tactic/sat_tactic.cpp
index 717bf7007..677540991 100644
--- a/src/sat/tactic/sat_tactic.cpp
+++ b/src/sat/tactic/sat_tactic.cpp
@@ -66,8 +66,6 @@ class sat_tactic : public tactic {
             CASSERT("sat_solver", m_solver.check_invariant());
             IF_VERBOSE(TACTIC_VERBOSITY_LVL, m_solver.display_status(verbose_stream()););
             TRACE("sat_dimacs", m_solver.display_dimacs(tout););
-			//m_solver.display_dimacs(std::cerr);
-            //exit(0);
 
             lbool r = m_solver.check();
             if (r == l_false) {
diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 5a5cbcf94..9ecc16ecf 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -28,7 +28,6 @@ Notes:
 #include"probe_arith.h"
 #include"quant_tactics.h"
 #include"qffpa_tactic.h"
-#include"sls_tactic.h"
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index f63b4fd8c..ae79446e3 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -37,14 +37,11 @@ Notes:
 #include"horn_tactic.h"
 #include"smt_solver.h"
 
-#include"sls_tactic.h"
-
 tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
-   //     return mk_qfbv_tactic(m, p);
-        return mk_qfbv_sls_tactic(m, p);
+        return mk_qfbv_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
     else if (logic=="QF_LIA")
diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp
index 3b4da2f2d..ac53ca0c8 100644
--- a/src/tactic/smtlogics/qfbv_tactic.cpp
+++ b/src/tactic/smtlogics/qfbv_tactic.cpp
@@ -93,32 +93,6 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) {
                             mk_sat_tactic(m));
 #endif    
     
-    /* use full sls
-    tactic * st = using_params(and_then(preamble_st,
-                                        cond(mk_is_qfbv_probe(),
-                                             cond(mk_is_qfbv_eq_probe(),
-                                                  and_then(mk_bv1_blaster_tactic(m),
-                                                           using_params(mk_smt_tactic(), solver_p)),
-                                                  and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))),
-                                             mk_smt_tactic())),
-                               main_p);*/
-
-    /* use pure dpll
-    tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),
-                                                  and_then(mk_bit_blaster_tactic(m),
-                                                           when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)),
-                                                                and_then(using_params(and_then(mk_simplify_tactic(m),
-                                                                                               mk_solve_eqs_tactic(m)),
-                                                                                      local_ctx_p),
-                                                                         if_no_proofs(cond(mk_produce_unsat_cores_probe(),
-                                                                                           mk_aig_tactic(),
-                                                                                           using_params(mk_aig_tactic(),
-                                                                                                        big_aig_p))))),
-                                                           new_sat),
-                                             mk_smt_tactic())),
-                               main_p);*/
-
     tactic * st = using_params(and_then(preamble_st,
                                         // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function
                                         // symbols. In this case, we should not use 

From a8d8e3e9e59b1f726399462bde034edae1e63aaf Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 19 Jan 2015 18:16:51 +0000
Subject: [PATCH 100/108] formatting

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 scripts/update_api.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/scripts/update_api.py b/scripts/update_api.py
index 2fbf42cca..d53bc5de3 100644
--- a/scripts/update_api.py
+++ b/scripts/update_api.py
@@ -266,7 +266,7 @@ def param2dotnet(p):
     elif k == OUT_ARRAY:
         return "[Out] %s[]" % type2dotnet(param_type(p))
     elif k == OUT_MANAGED_ARRAY:
-	return "[Out] out %s[]" % type2dotnet(param_type(p))
+        return "[Out] out %s[]" % type2dotnet(param_type(p))
     else:
         return type2dotnet(param_type(p))
 

From d20c7bc9eeaf952fd40f4604dac3c1a748507f56 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 19 Jan 2015 18:19:43 +0000
Subject: [PATCH 101/108] Added is_qfaufbv_probe and is_qfauflia_probe.

Potential performance disruption for some users:
Changed default_tactic to call the respective tactics,
where previously they would have run the default 'smt'
tactic.

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/arith/probe_arith.cpp        | 75 +++++++++++++++++++++++++
 src/tactic/arith/probe_arith.h          |  2 +
 src/tactic/portfolio/default_tactic.cpp |  6 +-
 src/tactic/probe.cpp                    | 38 +++++++++++++
 src/tactic/probe.h                      |  2 +
 5 files changed, 122 insertions(+), 1 deletion(-)

diff --git a/src/tactic/arith/probe_arith.cpp b/src/tactic/arith/probe_arith.cpp
index 45fc868ac..770281923 100644
--- a/src/tactic/arith/probe_arith.cpp
+++ b/src/tactic/arith/probe_arith.cpp
@@ -198,11 +198,75 @@ struct is_non_qflira_functor {
     }
 };
 
+struct is_non_qfauflira_functor {
+    struct found {};
+    ast_manager & m;
+    arith_util    m_arith_util;
+    array_util    m_array_util;
+    bool          m_int;
+    bool          m_real;
+
+    is_non_qfauflira_functor(ast_manager & _m, bool _int, bool _real) : 
+        m(_m), m_arith_util(_m), m_array_util(_m), m_int(_int), m_real(_real) {}
+
+    void operator()(var *) { throw found(); }
+
+    void operator()(quantifier *) { throw found(); }
+
+    bool compatible_sort(app * n) const {
+        if (m.is_bool(n))
+            return true;
+        if (m_int && m_arith_util.is_int(n))
+            return true;
+        if (m_real && m_arith_util.is_real(n))
+            return true;
+        if (m_array_util.is_array(n))
+            return true;
+        return false;
+    }
+
+    void operator()(app * n) {
+        if (!compatible_sort(n))
+            throw found();
+        family_id fid = n->get_family_id();
+        if (fid == m.get_basic_family_id())
+            return;
+        if (fid == m_arith_util.get_family_id()) {
+            switch (n->get_decl_kind()) {
+            case OP_LE:  case OP_GE: case OP_LT: case OP_GT:
+            case OP_ADD: case OP_NUM:
+                return;
+            case OP_MUL:
+                if (n->get_num_args() != 2)
+                    throw found();
+                if (!m_arith_util.is_numeral(n->get_arg(0)))
+                    throw found();
+                return;
+            case OP_TO_REAL:
+                if (!m_real)
+                    throw found();
+                break;
+            default:
+                throw found();
+            }
+            return;
+        }
+        if (is_uninterp(n))
+            return;
+        throw found();
+    }
+};
+
 static bool is_qflia(goal const & g) {
     is_non_qflira_functor p(g.m(), true, false);
     return !test(g, p);
 }
 
+static bool is_qfauflia(goal const & g) {
+    is_non_qfauflira_functor p(g.m(), true, false);
+    return !test(g, p);
+}
+
 class is_qflia_probe : public probe {
 public:
     virtual result operator()(goal const & g) {
@@ -210,6 +274,13 @@ public:
     }
 };
 
+class is_qfauflia_probe : public probe {
+public:
+    virtual result operator()(goal const & g) {
+        return is_qfauflia(g);
+    }
+};
+
 static bool is_qflra(goal const & g) {
     is_non_qflira_functor p(g.m(), false, true);
     return !test(g, p);
@@ -289,6 +360,10 @@ probe * mk_is_qflia_probe() {
     return alloc(is_qflia_probe);
 }
 
+probe * mk_is_qfauflia_probe() {
+    return alloc(is_qfauflia_probe);
+}
+
 probe * mk_is_qflra_probe() {
     return alloc(is_qflra_probe);
 }
diff --git a/src/tactic/arith/probe_arith.h b/src/tactic/arith/probe_arith.h
index 17e9efb28..83179098d 100644
--- a/src/tactic/arith/probe_arith.h
+++ b/src/tactic/arith/probe_arith.h
@@ -33,6 +33,7 @@ probe * mk_arith_max_degree_probe();
 */
 
 probe * mk_is_qflia_probe();
+probe * mk_is_qfauflia_probe();
 probe * mk_is_qflra_probe();
 probe * mk_is_qflira_probe();
 probe * mk_is_ilp_probe();
@@ -40,6 +41,7 @@ probe * mk_is_mip_probe();
 
 /*
   ADD_PROBE("is-qflia", "true if the goal is in QF_LIA.", "mk_is_qflia_probe()")
+  ADD_PROBE("is-qfauflia", "true if the goal is in QF_AUFLIA.", "mk_is_qfauflia_probe()")
   ADD_PROBE("is-qflra", "true if the goal is in QF_LRA.", "mk_is_qflra_probe()")
   ADD_PROBE("is-qflira", "true if the goal is in QF_LIRA.", "mk_is_qflira_probe()")
   ADD_PROBE("is-ilp", "true if the goal is ILP.", "mk_is_ilp_probe()")
diff --git a/src/tactic/portfolio/default_tactic.cpp b/src/tactic/portfolio/default_tactic.cpp
index 9ecc16ecf..4bd82b969 100644
--- a/src/tactic/portfolio/default_tactic.cpp
+++ b/src/tactic/portfolio/default_tactic.cpp
@@ -28,10 +28,14 @@ Notes:
 #include"probe_arith.h"
 #include"quant_tactics.h"
 #include"qffpa_tactic.h"
+#include"qfaufbv_tactic.h"
+#include"qfauflia_tactic.h"
 
 tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
     tactic * st = using_params(and_then(mk_simplify_tactic(m),
                                         cond(mk_is_qfbv_probe(),  mk_qfbv_tactic(m),
+                                        cond(mk_is_qfaufbv_probe(), mk_qfaufbv_tactic(m),
+                                        cond(mk_is_qfauflia_probe(), mk_qfauflia_tactic(m),
                                         cond(mk_is_qflia_probe(), mk_qflia_tactic(m),
                                         cond(mk_is_qflra_probe(), mk_qflra_tactic(m),
                                         cond(mk_is_qfnra_probe(), mk_qfnra_tactic(m),
@@ -39,7 +43,7 @@ tactic * mk_default_tactic(ast_manager & m, params_ref const & p) {
                                         cond(mk_is_nra_probe(),   mk_nra_tactic(m),
                                         cond(mk_is_lira_probe(),  mk_lira_tactic(m, p),
                                         cond(mk_is_qffpabv_probe(), mk_qffpa_tactic(m, p),
-                                             mk_smt_tactic()))))))))),
+                                             mk_smt_tactic()))))))))))),
                                p);
     return st;
 }
diff --git a/src/tactic/probe.cpp b/src/tactic/probe.cpp
index 1a696dc78..30a62fb5c 100644
--- a/src/tactic/probe.cpp
+++ b/src/tactic/probe.cpp
@@ -316,6 +316,44 @@ probe * mk_is_qfbv_probe() {
     return alloc(is_qfbv_probe); 
 }
 
+struct is_non_qfaufbv_predicate {
+    struct found {};
+    ast_manager & m;
+    bv_util       m_bv_util;
+    array_util    m_array_util;
+
+    is_non_qfaufbv_predicate(ast_manager & _m) : m(_m), m_bv_util(_m), m_array_util(_m) {}
+
+    void operator()(var *) { throw found(); }
+
+    void operator()(quantifier *) { throw found(); }
+
+    void operator()(app * n) {        
+        if (!m.is_bool(n) && !m_bv_util.is_bv(n) && !m_array_util.is_array(n))
+            throw found();
+        family_id fid = n->get_family_id();
+        if (fid == m.get_basic_family_id())
+            return;
+        if (fid == m_bv_util.get_family_id() || fid == m_array_util.get_family_id())
+            return;
+        if (is_uninterp(n))
+            return;
+
+        throw found();
+    }
+};
+
+class is_qfaufbv_probe : public probe {
+public:
+    virtual result operator()(goal const & g) {
+        return !test<is_non_qfaufbv_predicate>(g);
+    }
+};
+
+probe * mk_is_qfaufbv_probe() {
+    return alloc(is_qfaufbv_probe);
+}
+
 class num_consts_probe : public probe {
     bool         m_bool;   // If true, track only boolean constants. Otherwise, track only non boolean constants.
     char const * m_family; // (Ignored if m_bool == true), if != 0 and m_bool == true, then track only constants of the given family.
diff --git a/src/tactic/probe.h b/src/tactic/probe.h
index 2f61b340f..0cf8122e4 100644
--- a/src/tactic/probe.h
+++ b/src/tactic/probe.h
@@ -111,10 +111,12 @@ probe * mk_div(probe * p1, probe * p2);
 
 probe * mk_is_propositional_probe();
 probe * mk_is_qfbv_probe();
+probe * mk_is_qfaufbv_probe();
 
 /*
   ADD_PROBE("is-propositional", "true if the goal is in propositional logic.", "mk_is_propositional_probe()")
   ADD_PROBE("is-qfbv", "true if the goal is in QF_BV.", "mk_is_qfbv_probe()")
+  ADD_PROBE("is-qfaufbv", "true if the goal is in QF_AUFBV.", "mk_is_qfaufbv_probe()")
 */
 
 #endif

From 074ff311c072a8c240b515a54b9be2f705d9edd1 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Tue, 20 Jan 2015 15:19:31 +0000
Subject: [PATCH 102/108] BV-SLS final integration.

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 versions/z3-crsat-0.01.txt    | 12 ------------
 versions/z3-gsat-0.01.txt     | 10 ----------
 versions/z3-gsat-res-0.01.txt | 10 ----------
 versions/z3-wsat-0.01.txt     | 14 --------------
 versions/z3-wsat-0.01b.txt    | 14 --------------
 versions/z3-wsat-0.01c.txt    | 12 ------------
 versions/z3-wsat-0.01d.txt    | 11 -----------
 versions/z3-wsat-0.01e.txt    | 11 -----------
 versions/z3-wsat-0.02.txt     | 13 -------------
 versions/z3-wsat-res-0.01.txt | 13 -------------
 10 files changed, 120 deletions(-)
 delete mode 100644 versions/z3-crsat-0.01.txt
 delete mode 100644 versions/z3-gsat-0.01.txt
 delete mode 100644 versions/z3-gsat-res-0.01.txt
 delete mode 100644 versions/z3-wsat-0.01.txt
 delete mode 100644 versions/z3-wsat-0.01b.txt
 delete mode 100644 versions/z3-wsat-0.01c.txt
 delete mode 100644 versions/z3-wsat-0.01d.txt
 delete mode 100644 versions/z3-wsat-0.01e.txt
 delete mode 100644 versions/z3-wsat-0.02.txt
 delete mode 100644 versions/z3-wsat-res-0.01.txt

diff --git a/versions/z3-crsat-0.01.txt b/versions/z3-crsat-0.01.txt
deleted file mode 100644
index 49e1a1525..000000000
--- a/versions/z3-crsat-0.01.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-More focused (_FOCUS_ == 2) WalkSAT version.
-Variables are chosen among candidates in only one unsatisfied bit-vector term.
-Flip rate slightly slower; probably due to larger hash-table and recursive formula structure.
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 1
-#define _FOCUS_ 3
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-gsat-0.01.txt b/versions/z3-gsat-0.01.txt
deleted file mode 100644
index eb806a67f..000000000
--- a/versions/z3-gsat-0.01.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Basic GSAT version.
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 0
-#define _FOCUS_ 0
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-gsat-res-0.01.txt b/versions/z3-gsat-res-0.01.txt
deleted file mode 100644
index 6a211f2bc..000000000
--- a/versions/z3-gsat-res-0.01.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-Basic GSAT version corresponding to Christoph's original code.
-Restarts after 100 plateaus.
-
-#define _CNF_ 0
-#define _BFS_ 0
-#define _FOCUS_ 0
-#define _RESTARTS_ 1
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01.txt b/versions/z3-wsat-0.01.txt
deleted file mode 100644
index fec38518d..000000000
--- a/versions/z3-wsat-0.01.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Basic WalkSAT version.
-Variables are chosen among candidates in only ONE top level assertion.
-Flip rate increased by roughly 10%-300%.
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 1
-#define _FOCUS_ 1
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
-
-BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01b.txt b/versions/z3-wsat-0.01b.txt
deleted file mode 100644
index 8bcf2ffeb..000000000
--- a/versions/z3-wsat-0.01b.txt
+++ /dev/null
@@ -1,14 +0,0 @@
-Basic WalkSAT version.
-Variables are chosen among candidates in only ONE top level assertion.
-Chooses a random top level assertion instead of using a BFS approach (_BFS_ == 0).
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 0
-#define _FOCUS_ 1
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
-
-BUGGY VERSION! Uses wrong value for modulo operation in assertion selection.
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01c.txt b/versions/z3-wsat-0.01c.txt
deleted file mode 100644
index 223560e08..000000000
--- a/versions/z3-wsat-0.01c.txt
+++ /dev/null
@@ -1,12 +0,0 @@
-Basic WalkSAT version.
-Variables are chosen among candidates in only ONE top level assertion.
-AND is scored by average; OR is scored by inverse multiplication.
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 1
-#define _FOCUS_ 1
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 1
-#define _SCORE_OR_MUL_ 1
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01d.txt b/versions/z3-wsat-0.01d.txt
deleted file mode 100644
index 072191370..000000000
--- a/versions/z3-wsat-0.01d.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Basic WalkSAT version.
-Variables are chosen among candidates in only ONE top level assertion with MINIMAL top_score.
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 2
-#define _FOCUS_ 1
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.01e.txt b/versions/z3-wsat-0.01e.txt
deleted file mode 100644
index b018c5e0d..000000000
--- a/versions/z3-wsat-0.01e.txt
+++ /dev/null
@@ -1,11 +0,0 @@
-Basic WalkSAT version.
-Variables are chosen among candidates in only ONE top level assertion with MAXIMAL top_score.
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 3
-#define _FOCUS_ 1
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file
diff --git a/versions/z3-wsat-0.02.txt b/versions/z3-wsat-0.02.txt
deleted file mode 100644
index 34dcb157c..000000000
--- a/versions/z3-wsat-0.02.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Basic WalkSAT version.
-Variables are chosen among candidates in only ONE top level assertion.
-Score function reduced to 0/1.
-No restarts.
-
-#define _CNF_ 0
-#define _BFS_ 1
-#define _FOCUS_ 1
-#define _RESTARTS_ 0
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
-#define _WEIGHTED_DIST_ 1
\ No newline at end of file
diff --git a/versions/z3-wsat-res-0.01.txt b/versions/z3-wsat-res-0.01.txt
deleted file mode 100644
index 575180a59..000000000
--- a/versions/z3-wsat-res-0.01.txt
+++ /dev/null
@@ -1,13 +0,0 @@
-Basic WalkSAT version.
-Variables are chosen among candidates in only ONE top level assertion.
-Flip rate increased by roughly 10%-300% compared to GSAT.
-Restarts after 100 plateaus.
-Fps slightly decreased due to restarts. 
-
-#define _CNF_ 0
-#define _BFS_ 1
-#define _FOCUS_ 1
-#define _RESTARTS_ 1
-#define _TIMELIMIT_ 300
-#define _SCORE_AND_AVG_ 0
-#define _SCORE_OR_MUL_ 0
\ No newline at end of file

From 0746ede53733c6a4191dd588cba14ec83236e490 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Tue, 20 Jan 2015 15:59:25 +0000
Subject: [PATCH 103/108] BV SLS: Final adjustments

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/portfolio/smt_strategic_solver.cpp |  5 +---
 src/tactic/sls/sls_tactic.cpp                 |  3 +--
 src/tactic/sls/sls_tactic.h                   |  2 +-
 src/tactic/smtlogics/qfbv_tactic.cpp          | 26 -------------------
 4 files changed, 3 insertions(+), 33 deletions(-)

diff --git a/src/tactic/portfolio/smt_strategic_solver.cpp b/src/tactic/portfolio/smt_strategic_solver.cpp
index f63b4fd8c..586c3a349 100644
--- a/src/tactic/portfolio/smt_strategic_solver.cpp
+++ b/src/tactic/portfolio/smt_strategic_solver.cpp
@@ -37,14 +37,11 @@ Notes:
 #include"horn_tactic.h"
 #include"smt_solver.h"
 
-#include"sls_tactic.h"
-
 tactic * mk_tactic_for_logic(ast_manager & m, params_ref const & p, symbol const & logic) {
     if (logic=="QF_UF")
         return mk_qfuf_tactic(m, p);
     else if (logic=="QF_BV")
-   //     return mk_qfbv_tactic(m, p);
-        return mk_qfbv_sls_tactic(m, p);
+	    return mk_qfbv_tactic(m, p);
     else if (logic=="QF_IDL")
         return mk_qfidl_tactic(m, p);
     else if (logic=="QF_LIA")
diff --git a/src/tactic/sls/sls_tactic.cpp b/src/tactic/sls/sls_tactic.cpp
index 9bbed20bb..b06a047f7 100644
--- a/src/tactic/sls/sls_tactic.cpp
+++ b/src/tactic/sls/sls_tactic.cpp
@@ -158,8 +158,7 @@ tactic * mk_preamble(ast_manager & m, params_ref const & p) {
 }
 
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p) {
-    tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m));    
-    //tactic * t = and_then(mk_simplify_tactic(m), mk_nnf_tactic(m, p), mk_sls_tactic(m));    
+    tactic * t = and_then(mk_preamble(m, p), mk_sls_tactic(m, p));
     t->updt_params(p);
     return t;
 }
diff --git a/src/tactic/sls/sls_tactic.h b/src/tactic/sls/sls_tactic.h
index 50b8f0d5b..82ac1ce88 100644
--- a/src/tactic/sls/sls_tactic.h
+++ b/src/tactic/sls/sls_tactic.h
@@ -23,8 +23,8 @@ Notes:
 class ast_manager;
 class tactic;
 
-tactic * mk_sls_tactic(ast_manager & m, params_ref const & p = params_ref());
 tactic * mk_qfbv_sls_tactic(ast_manager & m, params_ref const & p = params_ref());
+
 /*
   ADD_TACTIC("qfbv-sls", "(try to) solve using stochastic local search for QF_BV.", "mk_qfbv_sls_tactic(m, p)")
 */
diff --git a/src/tactic/smtlogics/qfbv_tactic.cpp b/src/tactic/smtlogics/qfbv_tactic.cpp
index 3b4da2f2d..ac53ca0c8 100644
--- a/src/tactic/smtlogics/qfbv_tactic.cpp
+++ b/src/tactic/smtlogics/qfbv_tactic.cpp
@@ -93,32 +93,6 @@ tactic * mk_qfbv_tactic(ast_manager & m, params_ref const & p) {
                             mk_sat_tactic(m));
 #endif    
     
-    /* use full sls
-    tactic * st = using_params(and_then(preamble_st,
-                                        cond(mk_is_qfbv_probe(),
-                                             cond(mk_is_qfbv_eq_probe(),
-                                                  and_then(mk_bv1_blaster_tactic(m),
-                                                           using_params(mk_smt_tactic(), solver_p)),
-                                                  and_then(mk_nnf_tactic(m, p), mk_sls_tactic(m))),
-                                             mk_smt_tactic())),
-                               main_p);*/
-
-    /* use pure dpll
-    tactic * st = using_params(and_then(mk_simplify_tactic(m),
-                                        cond(mk_is_qfbv_probe(),
-                                                  and_then(mk_bit_blaster_tactic(m),
-                                                           when(mk_lt(mk_memory_probe(), mk_const_probe(MEMLIMIT)),
-                                                                and_then(using_params(and_then(mk_simplify_tactic(m),
-                                                                                               mk_solve_eqs_tactic(m)),
-                                                                                      local_ctx_p),
-                                                                         if_no_proofs(cond(mk_produce_unsat_cores_probe(),
-                                                                                           mk_aig_tactic(),
-                                                                                           using_params(mk_aig_tactic(),
-                                                                                                        big_aig_p))))),
-                                                           new_sat),
-                                             mk_smt_tactic())),
-                               main_p);*/
-
     tactic * st = using_params(and_then(preamble_st,
                                         // If the user sets HI_DIV0=false, then the formula may contain uninterpreted function
                                         // symbols. In this case, we should not use 

From 237577acc8e0d4fae8e57b4e48c3c086e70c23d1 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Tue, 20 Jan 2015 15:59:54 +0000
Subject: [PATCH 104/108] Bumping version to 4.4 Added to release notes

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 RELEASE_NOTES         | 8 ++++++--
 scripts/mk_project.py | 2 +-
 2 files changed, 7 insertions(+), 3 deletions(-)

diff --git a/RELEASE_NOTES b/RELEASE_NOTES
index ad2dcaf00..f185983a3 100644
--- a/RELEASE_NOTES
+++ b/RELEASE_NOTES
@@ -1,9 +1,13 @@
 RELEASE NOTES
 
-Version 4.3.3
+Version 4.4
 =============
 
-- Fixed bug in floating point models
+- New feature: Stochastic local search engine for bit-vector formulas (see the qfbv-sls tactic).
+  See also: Froehlich, Biere, Wintersteiger, Hamadi: Stochastic Local Search 
+  for Satisfiability Modulo Theories, AAAI 2015.
+
+- Fixed various bugs reported by Marc Brockschmidt, Venkatesh-Prasad Ranganath, Enric Carbonell, Morgan Deters, Tom Ball, and Codeplex users rsas, clockish, Heizmann.
 
 Version 4.3.2
 =============
diff --git a/scripts/mk_project.py b/scripts/mk_project.py
index b30bba609..225ef6413 100644
--- a/scripts/mk_project.py
+++ b/scripts/mk_project.py
@@ -9,7 +9,7 @@ from mk_util import *
 
 # Z3 Project definition
 def init_project_def():
-    set_version(4, 3, 3, 0)
+    set_version(4, 4, 0, 0)
     add_lib('util', [])
     add_lib('polynomial', ['util'], 'math/polynomial')
     add_lib('sat', ['util'])

From 83023c72116670742c8e6b1f470e08d1b80de158 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 21 Jan 2015 13:02:18 +0000
Subject: [PATCH 105/108] build fixes

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/tactic/sls/sls_tracker.h | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 89ef57871..798a03761 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -20,6 +20,8 @@ Notes:
 #ifndef _SLS_TRACKER_H_
 #define _SLS_TRACKER_H_
 
+#include<math.h>
+
 #include"for_each_expr.h"
 #include"ast_smt2_pp.h"
 #include"bv_decl_plugin.h"
@@ -39,7 +41,7 @@ class sls_tracker {
     mpz                   m_zero, m_one, m_two;
         
     struct value_score { 
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), touched(1), score_prune(0.0), has_pos_occ(0), has_neg_occ(0) { };
+        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), score_prune(0.0), has_pos_occ(0), has_neg_occ(0), touched(1) {};
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;

From 71e5f03b441cec399dae25cd15f6dd5fc4b657f8 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 21 Jan 2015 13:04:05 +0000
Subject: [PATCH 106/108] build fix

---
 src/tactic/sls/sls_tracker.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/tactic/sls/sls_tracker.h b/src/tactic/sls/sls_tracker.h
index 798a03761..87c0f962c 100644
--- a/src/tactic/sls/sls_tracker.h
+++ b/src/tactic/sls/sls_tracker.h
@@ -41,7 +41,7 @@ class sls_tracker {
     mpz                   m_zero, m_one, m_two;
         
     struct value_score { 
-        value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), distance(0), score_prune(0.0), has_pos_occ(0), has_neg_occ(0), touched(1) {};
+    value_score() : m(0), value(unsynch_mpz_manager::mk_z(0)), score(0.0), score_prune(0.0), has_pos_occ(0), has_neg_occ(0), distance(0), touched(1) {};
         ~value_score() { if (m) m->del(value); }
         unsynch_mpz_manager * m;
         mpz value;

From e20dc9f9a474e1228795c07cf6a1c8c522ba70c5 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 21 Jan 2015 13:35:25 +0000
Subject: [PATCH 107/108] typo

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/smt/smt_case_split_queue.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/smt/smt_case_split_queue.cpp b/src/smt/smt_case_split_queue.cpp
index 7a03224cf..5a4a6ff25 100644
--- a/src/smt/smt_case_split_queue.cpp
+++ b/src/smt/smt_case_split_queue.cpp
@@ -1091,7 +1091,7 @@ namespace smt {
     case_split_queue * mk_case_split_queue(context & ctx, smt_params & p) {
         if (p.m_relevancy_lvl < 2 && (p.m_case_split_strategy == CS_RELEVANCY || p.m_case_split_strategy == CS_RELEVANCY_ACTIVITY || 
                                       p.m_case_split_strategy == CS_RELEVANCY_GOAL)) {
-            warning_msg("relevacy must be enabled to use option CASE_SPLIT=3, 4 or 5");
+            warning_msg("relevancy must be enabled to use option CASE_SPLIT=3, 4 or 5");
             p.m_case_split_strategy = CS_ACTIVITY;
         }
         if (p.m_auto_config && (p.m_case_split_strategy == CS_RELEVANCY || p.m_case_split_strategy == CS_RELEVANCY_ACTIVITY || 

From ae792f18917d34ad02279999bbdf29d132f94a97 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Wed, 21 Jan 2015 13:47:32 +0000
Subject: [PATCH 108/108] avoid spurious warning message

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 src/smt/smt_model_checker.cpp | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/smt/smt_model_checker.cpp b/src/smt/smt_model_checker.cpp
index 7053d63ec..163003c01 100644
--- a/src/smt/smt_model_checker.cpp
+++ b/src/smt/smt_model_checker.cpp
@@ -282,6 +282,7 @@ namespace smt {
         if (!m_fparams) {
             m_fparams = alloc(smt_params, m_context->get_fparams());
             m_fparams->m_relevancy_lvl = 0; // no relevancy since the model checking problems are quantifier free
+            m_fparams->m_case_split_strategy = CS_ACTIVITY; // avoid warning messages about smt.case_split >= 3.
         }
         if (!m_aux_context) {
             symbol logic;