diff --git a/src/tactic/smtlogics/qflra_tactic.cpp b/src/tactic/smtlogics/qflra_tactic.cpp
index 1fbecef2d..0865f3b47 100644
--- a/src/tactic/smtlogics/qflra_tactic.cpp
+++ b/src/tactic/smtlogics/qflra_tactic.cpp
@@ -22,7 +22,6 @@ Notes:
 #include"solve_eqs_tactic.h"
 #include"elim_uncnstr_tactic.h"
 #include"smt_tactic.h"
-// include"mip_tactic.h"
 #include"recover_01_tactic.h"
 #include"ctx_simplify_tactic.h"
 #include"probe_arith.h"
@@ -75,14 +74,15 @@ tactic * mk_qflra_tactic(ast_manager & m, params_ref const & p) {
 #if 0
 
     params_ref simplex_0, simplex_1, simplex_2;
-    simplex_0.set("lp.simplex_strategy", 0);    
-    simplex_1.set("lp.simplex_strategy", 1);    
-    simplex_2.set("lp.simplex_strategy", 1);
+    simplex_0.set_uint("lp.simplex_strategy", 0);    
+    simplex_1.set_uint("lp.simplex_strategy", 1);    
+    simplex_2.set_uint("lp.simplex_strategy", 2);
     
-    tactic* lp_par = par_or(using_params(mk_smt_tactic(), simplex_0), 
-                            using_params(mk_smt_tactic(), simplex_1), 
-                            using_params(mk_smt_tactic(), simplex_2));
-                            
-#endif
+    return par(using_params(mk_smt_tactic(), simplex_0), 
+               using_params(mk_smt_tactic(), simplex_1), 
+               using_params(mk_smt_tactic(), simplex_2));
+#else
     return using_params(using_params(mk_smt_tactic(), pivot_p), p);
+#endif
+
 }
diff --git a/src/test/lp.cpp b/src/test/lp.cpp
index f1df5b05e..235dab960 100644
--- a/src/test/lp.cpp
+++ b/src/test/lp.cpp
@@ -34,6 +34,10 @@ Author: Lev Nachmanson
 namespace lean {
 unsigned seed = 1;
 
+    random_gen g_rand;
+    static unsigned my_random() {
+        return g_rand();
+    }
 struct simple_column_namer:public column_namer
 {
     std::string get_column_name(unsigned j) const override {
@@ -1104,7 +1108,7 @@ void update_settings(argument_parser & args_parser, lp_settings& settings) {
         settings.harris_feasibility_tolerance = d;
     }
     if (get_int_from_args_parser("--random_seed", args_parser, n)) {
-        settings.random_seed = n;
+        settings.random_seed(n);
     }
     if (get_int_from_args_parser("--simplex_strategy", args_parser, n)) {
         settings.simplex_strategy() = static_cast<simplex_strategy_enum>(n);
diff --git a/src/util/lp/lar_core_solver.h b/src/util/lp/lar_core_solver.h
index ba5bbaa62..71d69c3a4 100644
--- a/src/util/lp/lar_core_solver.h
+++ b/src/util/lp/lar_core_solver.h
@@ -367,7 +367,7 @@ public:
                       s.m_x[j] = s.m_low_bounds[j];
                       break;
                   case column_type::boxed:
-                      if (my_random() % 2) {
+                      if (settings().random_next() % 2) {
                           s.m_x[j] = s.m_low_bounds[j];
                       } else {
                           s.m_x[j] = s.m_upper_bounds[j];
diff --git a/src/util/lp/lp_core_solver_base.h b/src/util/lp/lp_core_solver_base.h
index 4e9d3dfa3..a12b7b5d2 100644
--- a/src/util/lp/lp_core_solver_base.h
+++ b/src/util/lp/lp_core_solver_base.h
@@ -348,7 +348,7 @@ public:
             if (x_is_at_bound(j))
                 break; // we should preserve x if possible
             // snap randomly
-            if (my_random() % 2 == 1) 
+            if (m_settings.random_next() % 2 == 1) 
                 m_x[j] = m_low_bounds[j];
             else
                 m_x[j] = m_upper_bounds[j];
diff --git a/src/util/lp/lp_core_solver_base.hpp b/src/util/lp/lp_core_solver_base.hpp
index 7dae0535a..a0dba9de7 100644
--- a/src/util/lp/lp_core_solver_base.hpp
+++ b/src/util/lp/lp_core_solver_base.hpp
@@ -64,8 +64,7 @@ allocate_basis_heading() { // the rest of initilization will be handled by the f
     lean_assert(basis_heading_is_correct());
 }
 template <typename T, typename X> void lp_core_solver_base<T, X>::
-init() {
-    my_random_init(m_settings.random_seed);
+init() {    
     allocate_basis_heading();
     if (m_settings.use_lu())
         init_factorization(m_factorization, m_A, m_basis, m_settings);
diff --git a/src/util/lp/lp_dual_core_solver.hpp b/src/util/lp/lp_dual_core_solver.hpp
index 918beb586..6565331b3 100644
--- a/src/util/lp/lp_dual_core_solver.hpp
+++ b/src/util/lp/lp_dual_core_solver.hpp
@@ -537,7 +537,7 @@ template <typename T, typename X> unsigned lp_dual_core_solver<T, X>::get_number
     if (this->m_m() > 300) {
         s = (unsigned)((s / 100.0) * this->m_settings.percent_of_entering_to_check);
     }
-    return my_random() % s + 1;
+    return this->m_settings.random_next() % s + 1;
 }
 
 template <typename T, typename X> bool lp_dual_core_solver<T, X>::delta_keeps_the_sign(int initial_delta_sign, const T & delta) {
@@ -715,7 +715,7 @@ template <typename T, typename X> void lp_dual_core_solver<T, X>::update_xb_afte
 
 template <typename T, typename X> void lp_dual_core_solver<T, X>::one_iteration() {
     unsigned number_of_rows_to_try = get_number_of_rows_to_try_for_leaving();
-    unsigned offset_in_rows = my_random() % this->m_m();
+    unsigned offset_in_rows = this->m_settings.random_next() % this->m_m();
     if (this->get_status() == TENTATIVE_DUAL_UNBOUNDED) {
         number_of_rows_to_try = this->m_m();
     } else {
diff --git a/src/util/lp/lp_primal_core_solver.h b/src/util/lp/lp_primal_core_solver.h
index 93ecd3c08..3fada1e5d 100644
--- a/src/util/lp/lp_primal_core_solver.h
+++ b/src/util/lp/lp_primal_core_solver.h
@@ -76,10 +76,10 @@ public:
     //             choices.clear();
     //             choices.push_back(i);
     //             len = row_len;
-    //             if (my_random() % 10) break;
+    //             if (m_settings.random_next() % 10) break;
     //         } else if (row_len == len) {
     //             choices.push_back(i);
-    //             if (my_random() % 10) break;
+    //             if (m_settings.random_next() % 10) break;
     //         }
     //     }
 
@@ -89,7 +89,7 @@ public:
     //     if (choices.size() == 1)
     //         return choices[0];
         
-    //     unsigned k = my_random() % choices.size();
+    //     unsigned k = this->m_settings.random_next() % choices.size();
     //     return choices[k];
     //     #endif
     // }
@@ -287,7 +287,7 @@ public:
                 choices.clear();
                 choices.push_back(&rc);
             } else if (damage == num_of_non_free_basics &&
-                       this->m_A.m_columns[j].size() <= len && (my_random() % 2)) {
+                       this->m_A.m_columns[j].size() <= len && (this->m_settings.random_next() % 2)) {
                 choices.push_back(&rc);
                 len = this->m_A.m_columns[j].size();
             }
@@ -299,7 +299,7 @@ public:
             return -1;
         }
         const row_cell<T>* rc = choices.size() == 1? choices[0] :
-            choices[my_random() % choices.size()];
+            choices[this->m_settings.random_next() % choices.size()];
 
         a_ent = rc->m_value;
         return rc->m_j;
diff --git a/src/util/lp/lp_primal_core_solver.hpp b/src/util/lp/lp_primal_core_solver.hpp
index 4299edb96..47eec468a 100644
--- a/src/util/lp/lp_primal_core_solver.hpp
+++ b/src/util/lp/lp_primal_core_solver.hpp
@@ -199,7 +199,7 @@ int lp_primal_core_solver<T, X>::choose_entering_column_presize(unsigned number_
             entering_iter = non_basis_iter;
             if (number_of_benefitial_columns_to_go_over)
                 number_of_benefitial_columns_to_go_over--;
-        } else if (t == j_nz && my_random() % 2 == 0) {
+        } else if (t == j_nz && this->m_settings.random_next() % 2 == 0) {
             entering_iter = non_basis_iter;
         }
     }// while (number_of_benefitial_columns_to_go_over && initial_offset_in_non_basis != offset_in_nb);
@@ -268,7 +268,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::advance_on_so
         if (slope_at_entering * m_sign_of_entering_delta > - m_epsilon_of_reduced_cost) { // the slope started to increase infeasibility
             break;
         } else {
-            if ((numeric_traits<T>::precise() == false) || ( numeric_traits<T>::is_zero(slope_at_entering) && my_random() % 2 == 0)) {
+            if ((numeric_traits<T>::precise() == false) || ( numeric_traits<T>::is_zero(slope_at_entering) && this->m_settings.random_next() % 2 == 0)) {
                 // it is not cost benefitial to advance the delta more, so just break to increas the randomness
                 break;
             }
@@ -307,7 +307,7 @@ find_leaving_on_harris_theta(X const & harris_theta, X & t) {
     // we also know that harris_theta is limited, so we will find a leaving
     zero_harris_eps();
     unsigned steps = this->m_ed.m_index.size();
-    unsigned k = my_random() % steps;
+    unsigned k = this->m_settings.random_next() % steps;
     unsigned initial_k = k;
     do {
         unsigned i = this->m_ed.m_index[k];
@@ -398,7 +398,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
         return find_leaving_and_t_with_breakpoints(entering, t);
     bool unlimited = true;
     unsigned steps = this->m_ed.m_index.size();
-    unsigned k = my_random() % steps;
+    unsigned k = this->m_settings.random_next() % steps;
     unsigned initial_k = k;
     unsigned row_min_nz = this->m_n() + 1;
     m_leaving_candidates.clear();
@@ -454,7 +454,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
         t = ratio;
         return entering;
     }
-    k = my_random() % m_leaving_candidates.size();
+    k = this->m_settings.random_next() % m_leaving_candidates.size();
     return m_leaving_candidates[k];
 }
 
@@ -833,7 +833,7 @@ template <typename T, typename X>  unsigned lp_primal_core_solver<T, X>::get_num
     if (ret == 0) {
         return 0;
     }
-    return std::max(static_cast<unsigned>(my_random() % ret), 1u);
+    return std::max(static_cast<unsigned>(this->m_settings.random_next() % ret), 1u);
 }
 
 template <typename T, typename X> void lp_primal_core_solver<T, X>::print_column_norms(std::ostream & out) {
@@ -961,7 +961,7 @@ template <typename T, typename X> void lp_primal_core_solver<T, X>::init_column_
     for (unsigned j = 0; j < this->m_n(); j++) {
         this->m_column_norms[j] = T(static_cast<int>(this->m_A.m_columns[j].size() + 1)) 
             
-            + T(static_cast<int>(my_random() % 10000)) / T(100000);
+            + T(static_cast<int>(this->m_settings.random_next() % 10000)) / T(100000);
     }
 }
 
diff --git a/src/util/lp/lp_primal_core_solver_tableau.hpp b/src/util/lp/lp_primal_core_solver_tableau.hpp
index 6ce491960..0c09c22c9 100644
--- a/src/util/lp/lp_primal_core_solver_tableau.hpp
+++ b/src/util/lp/lp_primal_core_solver_tableau.hpp
@@ -62,7 +62,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::choose_enteri
             if (number_of_benefitial_columns_to_go_over)
                 number_of_benefitial_columns_to_go_over--;
         }
-        else if (t == j_nz && my_random() % 2 == 0) {
+        else if (t == j_nz && this->m_settings.random_next() % 2 == 0) {
             entering_iter = non_basis_iter;
         }
     }// while (number_of_benefitial_columns_to_go_over && initial_offset_in_non_basis != offset_in_nb);
@@ -293,7 +293,7 @@ template <typename T, typename X> int lp_primal_core_solver<T, X>::find_leaving_
     }
     if (m_leaving_candidates.size() == 1)
         return m_leaving_candidates[0];
-    k = my_random() % m_leaving_candidates.size();
+    k = this->m_settings.random_next() % m_leaving_candidates.size();
     return m_leaving_candidates[k];
 }
 template <typename T, typename X> void lp_primal_core_solver<T, X>::init_run_tableau() {
diff --git a/src/util/lp/lp_settings.h b/src/util/lp/lp_settings.h
index e97f5f5f5..6b6aba2ad 100644
--- a/src/util/lp/lp_settings.h
+++ b/src/util/lp/lp_settings.h
@@ -71,8 +71,6 @@ template <typename X> bool is_epsilon_small(const X & v, const double& eps);
 
 int get_millisecond_count();
 int get_millisecond_span(int start_time);
-unsigned my_random();
-void my_random_init(long unsigned seed);
 
 
 class lp_resource_limit {
@@ -111,6 +109,7 @@ private:
     std::ostream* m_message_out;
 
     stats  m_stats;
+    random_gen m_rand;
 
 public:
     unsigned reps_in_scaler;
@@ -194,16 +193,15 @@ public:
                     m_bound_propagation ( true),
                     presolve_with_double_solver_for_lar(true),
                     m_simplex_strategy(simplex_strategy_enum::tableau_rows),
-                  report_frequency(1000),
-                  print_statistics(false),
-                  column_norms_update_frequency(12000),
-                  scale_with_ratio(true),
-                  density_threshold(0.7),
-                  use_breakpoints_in_feasibility_search(false),
-                  random_seed(1),
-                  max_row_length_for_bound_propagation(300),
-                  backup_costs(true),
-                  column_number_threshold_for_using_lu_in_lar_solver(4000)
+                    report_frequency(1000),
+                    print_statistics(false),
+                    column_norms_update_frequency(12000),
+                    scale_with_ratio(true),
+                    density_threshold(0.7),
+                    use_breakpoints_in_feasibility_search(false),
+                    max_row_length_for_bound_propagation(300),
+                    backup_costs(true),
+                    column_number_threshold_for_using_lu_in_lar_solver(4000)
     {}
 
     void set_resource_limit(lp_resource_limit& lim) { m_resource_limit = &lim; }
@@ -305,8 +303,8 @@ public:
     static unsigned ddd; // used for debugging    
 #endif
     bool use_breakpoints_in_feasibility_search;
-    unsigned random_seed;
-    static unsigned long random_next;
+    unsigned random_next() { return m_rand(); }
+    void random_seed(unsigned s) { m_rand.set_seed(s); }
     unsigned max_row_length_for_bound_propagation;
     bool backup_costs;
     unsigned column_number_threshold_for_using_lu_in_lar_solver;
diff --git a/src/util/lp/lp_settings.hpp b/src/util/lp/lp_settings.hpp
index d110d51af..b57a3acda 100644
--- a/src/util/lp/lp_settings.hpp
+++ b/src/util/lp/lp_settings.hpp
@@ -67,15 +67,6 @@ int get_millisecond_span(int start_time) {
 
 
 
-void my_random_init(long unsigned seed) {
-    lp_settings::random_next = seed;   
-}
-
-unsigned my_random() {
-    lp_settings::random_next = lp_settings::random_next * 1103515245 + 12345;
-    return((unsigned)(lp_settings::random_next/65536) % 32768);
-}
-
 template <typename T>
 bool vectors_are_equal(T * a, vector<T>  &b, unsigned n) {
     if (numeric_traits<T>::precise()) {
@@ -126,7 +117,6 @@ bool vectors_are_equal(const vector<T> & a, const vector<T>  &b) {
     }
     return true;
 }
-unsigned long lp_settings::random_next = 1;
 #ifdef LEAN_DEBUG
 unsigned lp_settings::ddd = 0;
 #endif
diff --git a/src/util/lp/random_updater.hpp b/src/util/lp/random_updater.hpp
index 635053a09..7c6a0539f 100644
--- a/src/util/lp/random_updater.hpp
+++ b/src/util/lp/random_updater.hpp
@@ -136,7 +136,7 @@ void random_updater::shift_var(unsigned j, interval & r) {
 }
 
 numeric_pair<mpq> random_updater::get_random_from_interval(interval & r) {
-    unsigned rand = my_random();
+    unsigned rand = m_core_solver.settings().random_next();
     if ((!r.low_bound_is_set)  && (!r.upper_bound_is_set))
         return numeric_pair<mpq>(rand % range, 0);
     if (r.low_bound_is_set  && (!r.upper_bound_is_set))