From 9f2bafbf10d44e5395c42666b5fbc95dbafcebc0 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Wed, 11 Jul 2018 08:52:13 -0700
Subject: [PATCH 01/10] tidy model generator

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/smt/smt_model_generator.cpp | 71 +++++++++++++++------------------
 src/smt/smt_model_generator.h   | 10 +++--
 src/smt/theory_datatype.cpp     |  1 +
 3 files changed, 39 insertions(+), 43 deletions(-)

diff --git a/src/smt/smt_model_generator.cpp b/src/smt/smt_model_generator.cpp
index 5417785d6..190f7f79e 100644
--- a/src/smt/smt_model_generator.cpp
+++ b/src/smt/smt_model_generator.cpp
@@ -28,6 +28,15 @@ Revision History:
 
 namespace smt {
 
+    void fresh_value_proc::get_dependencies(buffer<model_value_dependency>& result) { 
+        result.push_back(model_value_dependency(m_value)); 
+    }
+
+    std::ostream& operator<<(std::ostream& out, model_value_dependency const& src) {
+        if (src.is_fresh_value()) return out << "fresh!" << src.get_value()->get_idx();
+        else return out << "#" << src.get_enode()->get_owner_id();
+    }
+
     model_generator::model_generator(ast_manager & m):
         m_manager(m),
         m_context(nullptr),
@@ -161,20 +170,20 @@ namespace smt {
                                          source2color & colors, 
                                          obj_hashtable<sort> & already_traversed, 
                                          svector<source> & todo) {
+
         if (src.is_fresh_value()) {
-            // there is an implicit dependency between a fresh value stub of sort S and the root enodes of sort S that are not associated with fresh values.
+            // there is an implicit dependency between a fresh value stub of 
+            // sort S and the root enodes of sort S that are not associated with fresh values.
+            //
             sort * s     = src.get_value()->get_sort();
             if (already_traversed.contains(s))
                 return true;
             bool visited = true;
-            unsigned sz  = roots.size();
-            for (unsigned i = 0; i < sz; i++) {
-                enode * r     = roots[i];
+            for (enode * r : roots) {
                 if (m_manager.get_sort(r->get_owner()) != s)
                     continue;
                 SASSERT(r == r->get_root());
-                model_value_proc * proc = nullptr;
-                root2proc.find(r, proc);
+                model_value_proc * proc = root2proc[r];
                 SASSERT(proc);
                 if (proc->is_fresh())
                     continue; // r is associated with a fresh value...
@@ -192,17 +201,12 @@ namespace smt {
         enode * n = src.get_enode();
         SASSERT(n == n->get_root());
         bool visited = true;
-        model_value_proc * proc = nullptr;
-        root2proc.find(n, proc);
-        SASSERT(proc);
+        model_value_proc * proc = root2proc[n];
         buffer<model_value_dependency> dependencies;
         proc->get_dependencies(dependencies);
         for (model_value_dependency const& dep : dependencies) {
             visit_child(dep, colors, todo, visited);
-            TRACE("mg_top_sort", tout << "#" << n->get_owner_id() << " -> ";
-                  if (dep.is_fresh_value()) tout << "fresh!" << dep.get_value()->get_idx();
-                  else tout << "#" << dep.get_enode()->get_owner_id();
-                  tout << "\n";);
+            TRACE("mg_top_sort", tout << "#" << n->get_owner_id() << " -> " << dep << " already visited: " << visited << "\n";);
         }
         return visited;
     }
@@ -215,9 +219,7 @@ namespace smt {
                                          svector<source> & todo,
                                          svector<source> & sorted_sources) {
         TRACE("mg_top_sort", tout << "process source, is_fresh: " << src.is_fresh_value() << " ";
-              if (src.is_fresh_value()) tout << "fresh!" << src.get_value()->get_idx();
-              else tout << "#" << src.get_enode()->get_owner_id();
-              tout << ", todo.size(): " << todo.size() << "\n";);
+              tout << src << ", todo.size(): " << todo.size() << "\n";);
         int color     = get_color(colors, src);
         SASSERT(color != Grey);
         if (color == Black)
@@ -227,17 +229,16 @@ namespace smt {
         while (!todo.empty()) {
             source curr = todo.back();
             TRACE("mg_top_sort", tout << "current source, is_fresh: " << curr.is_fresh_value() << " ";
-                  if (curr.is_fresh_value()) tout << "fresh!" << curr.get_value()->get_idx();
-                  else tout << "#" << curr.get_enode()->get_owner_id();
-                  tout << ", todo.size(): " << todo.size() << "\n";);
+                  tout << curr << ", todo.size(): " << todo.size() << "\n";);
             switch (get_color(colors, curr)) {
             case White:
                 set_color(colors, curr, Grey);
                 visit_children(curr, roots, root2proc, colors, already_traversed, todo);
                 break;
             case Grey:
-                SASSERT(visit_children(curr, roots, root2proc, colors, already_traversed, todo));
+                // SASSERT(visit_children(curr, roots, root2proc, colors, already_traversed, todo));
                 set_color(colors, curr, Black);
+                TRACE("mg_top_sort", tout << "append " << curr << "\n";);
                 sorted_sources.push_back(curr);
                 break;
             case Black:
@@ -266,18 +267,15 @@ namespace smt {
         // topological sort
 
         // traverse all extra fresh values...
-        unsigned sz = m_extra_fresh_values.size();
-        for (unsigned i = 0; i < sz; i++) {
-            extra_fresh_value * f = m_extra_fresh_values[i];
+        for (extra_fresh_value * f : m_extra_fresh_values) {
             process_source(source(f), roots, root2proc, colors, already_traversed, todo, sorted_sources);
         }
 
         // traverse all enodes that are associated with fresh values...
-        sz = roots.size();
+        unsigned sz = roots.size();
         for (unsigned i = 0; i < sz; i++) {
             enode * r     = roots[i];
-            model_value_proc * proc = nullptr;
-            root2proc.find(r, proc);
+            model_value_proc * proc = root2proc[r];
             SASSERT(proc);
             if (!proc->is_fresh())
                 continue;
@@ -303,43 +301,38 @@ namespace smt {
         TRACE("sorted_sources",
               for (source const& curr : sources) {
                   if (curr.is_fresh_value()) {
-                      tout << "fresh!" << curr.get_value()->get_idx() << " " << mk_pp(curr.get_value()->get_sort(), m_manager) << "\n";
+                      tout << curr << " " << mk_pp(curr.get_value()->get_sort(), m_manager) << "\n";
                   }
                   else {
                       enode * n = curr.get_enode();
                       SASSERT(n->get_root() == n);
                       sort * s = m_manager.get_sort(n->get_owner());
-                      tout << "#" << n->get_owner_id() << " " << mk_pp(s, m_manager);
-                      model_value_proc * proc = 0;
-                      root2proc.find(n, proc);
-                      SASSERT(proc);
-                      tout << " is_fresh: " << proc->is_fresh() << "\n";
+                      tout << curr << " " << mk_pp(s, m_manager);
+                      tout << " is_fresh: " << root2proc[n]->is_fresh() << "\n";
                   }
               });
         for (source const& curr : sources) {
             if (curr.is_fresh_value()) {
                 sort * s = curr.get_value()->get_sort();
-                TRACE("model_fresh_bug", tout << "mk fresh!" << curr.get_value()->get_idx() << " : " << mk_pp(s, m_manager) << "\n";);
+                TRACE("model_fresh_bug", tout << curr << " : " << mk_pp(s, m_manager) << "\n";);
                 expr * val = m_model->get_fresh_value(s);
-                TRACE("model_fresh_bug", tout << "mk fresh!" << curr.get_value()->get_idx() << " := #" << (val == 0 ? UINT_MAX : val->get_id()) << "\n";);
+                TRACE("model_fresh_bug", tout << curr << " := #" << (val == nullptr ? UINT_MAX : val->get_id()) << "\n";);
                 m_asts.push_back(val);
                 curr.get_value()->set_value(val);
             }
             else {
                 enode * n = curr.get_enode();
                 SASSERT(n->get_root() == n);
-                TRACE("mg_top_sort", tout << "#" << n->get_owner_id() << "\n";);
+                TRACE("mg_top_sort", tout << curr << "\n";);
                 dependencies.reset();
                 dependency_values.reset();
-                model_value_proc * proc = nullptr;
-                VERIFY(root2proc.find(n, proc));
+                model_value_proc * proc = root2proc[n];
                 SASSERT(proc);
                 proc->get_dependencies(dependencies);
                 for (model_value_dependency const& d : dependencies) {
                     if (d.is_fresh_value()) {
                         CTRACE("mg_top_sort", !d.get_value()->get_value(), 
-                               tout << "#" << n->get_owner_id() << " -> ";
-                               tout << "fresh!" << d.get_value()->get_idx() << "\n";);
+                               tout << "#" << n->get_owner_id() << " -> " << d << "\n";);
                         SASSERT(d.get_value()->get_value());
                         dependency_values.push_back(d.get_value()->get_value());
                     }
diff --git a/src/smt/smt_model_generator.h b/src/smt/smt_model_generator.h
index 7466b8877..1f69eb324 100644
--- a/src/smt/smt_model_generator.h
+++ b/src/smt/smt_model_generator.h
@@ -100,14 +100,16 @@ namespace smt {
             extra_fresh_value * m_value; //!< When m_fresh == true, contains the sort of the fresh value
         };
     public:
-        model_value_dependency():m_fresh(true), m_value(nullptr) {}
-        model_value_dependency(enode * n):m_fresh(false), m_enode(n->get_root()) {}
-        model_value_dependency(extra_fresh_value * v):m_fresh(true), m_value(v) {}
+        model_value_dependency():m_fresh(true), m_value(nullptr) { }
+        explicit model_value_dependency(enode * n):m_fresh(false), m_enode(n->get_root()) {}
+        explicit model_value_dependency(extra_fresh_value * v) :m_fresh(true), m_value(v) { SASSERT(v); }
         bool is_fresh_value() const { return m_fresh; }
         enode * get_enode() const { SASSERT(!is_fresh_value()); return m_enode; }
         extra_fresh_value * get_value() const { SASSERT(is_fresh_value()); return m_value; }
     };
 
+    std::ostream& operator<<(std::ostream& out, model_value_dependency const& d);
+
     typedef model_value_dependency source;
 
     struct source_hash_proc {
@@ -166,7 +168,7 @@ namespace smt {
         extra_fresh_value * m_value;
     public:
         fresh_value_proc(extra_fresh_value * v):m_value(v) {}
-        void get_dependencies(buffer<model_value_dependency> & result) override { result.push_back(m_value); }
+        void get_dependencies(buffer<model_value_dependency> & result) override;
         app * mk_value(model_generator & m, ptr_vector<expr> & values) override { return to_app(values[0]); }
         bool is_fresh() const override { return true; }
     };
diff --git a/src/smt/theory_datatype.cpp b/src/smt/theory_datatype.cpp
index 049555297..c3befced6 100644
--- a/src/smt/theory_datatype.cpp
+++ b/src/smt/theory_datatype.cpp
@@ -636,6 +636,7 @@ namespace smt {
         void add_dependency(enode * n) { m_dependencies.push_back(model_value_dependency(n)); }
         ~datatype_value_proc() override {}
         void get_dependencies(buffer<model_value_dependency> & result) override {
+            for (model_value_dependency& d : m_dependencies) { }
             result.append(m_dependencies.size(), m_dependencies.c_ptr());
         }
         app * mk_value(model_generator & mg, ptr_vector<expr> & values) override {

From 3a5aebd1d32c8cd889b582dde4277a3e0fb11d67 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Wed, 11 Jul 2018 08:52:57 -0700
Subject: [PATCH 02/10] tidy model generator

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/smt/theory_datatype.cpp | 1 -
 1 file changed, 1 deletion(-)

diff --git a/src/smt/theory_datatype.cpp b/src/smt/theory_datatype.cpp
index c3befced6..049555297 100644
--- a/src/smt/theory_datatype.cpp
+++ b/src/smt/theory_datatype.cpp
@@ -636,7 +636,6 @@ namespace smt {
         void add_dependency(enode * n) { m_dependencies.push_back(model_value_dependency(n)); }
         ~datatype_value_proc() override {}
         void get_dependencies(buffer<model_value_dependency> & result) override {
-            for (model_value_dependency& d : m_dependencies) { }
             result.append(m_dependencies.size(), m_dependencies.c_ptr());
         }
         app * mk_value(model_generator & mg, ptr_vector<expr> & values) override {

From 167969d6c2148b274749eaa98967862912e59d61 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Fri, 13 Jul 2018 07:52:36 -0700
Subject: [PATCH 03/10] remove debug/non-debug difference

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/smt/theory_lra.cpp     |  2 --
 src/util/lp/hnf_cutter.h   | 28 +++++++++++++---------------
 src/util/lp/int_solver.cpp | 26 ++++++++++++++++++--------
 3 files changed, 31 insertions(+), 25 deletions(-)

diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp
index 3bdd2d784..ff5b72159 100644
--- a/src/smt/theory_lra.cpp
+++ b/src/smt/theory_lra.cpp
@@ -2712,7 +2712,6 @@ public:
         if (dump_lemmas()) {
             unsigned id = ctx().display_lemma_as_smt_problem(m_core.size(), m_core.c_ptr(), m_eqs.size(), m_eqs.c_ptr(), false_literal);
             (void)id;
-            //SASSERT(id != 55);
         }
     }
 
@@ -2732,7 +2731,6 @@ public:
         if (dump_lemmas()) {                
             unsigned id = ctx().display_lemma_as_smt_problem(m_core.size(), m_core.c_ptr(), m_eqs.size(), m_eqs.c_ptr(), lit);
             (void)id;
-            // SASSERT(id != 71);
         }
     }
 
diff --git a/src/util/lp/hnf_cutter.h b/src/util/lp/hnf_cutter.h
index dff0b8ef8..9a06e1bc9 100644
--- a/src/util/lp/hnf_cutter.h
+++ b/src/util/lp/hnf_cutter.h
@@ -177,43 +177,41 @@ public:
 
     bool overflow() const { return m_overflow; }
     
-    lia_move create_cut(lar_term& t, mpq& k, explanation& ex, bool & upper
-                        #ifdef Z3DEBUG
-                        ,
-                        const vector<mpq> & x0
-                        #endif
-                        ) {
+    lia_move create_cut(lar_term& t, mpq& k, explanation& ex, bool & upper, const vector<mpq> & x0) {
         // we suppose that x0 has at least one non integer element 
+        (void)x0;
+
         init_matrix_A();
         svector<unsigned> basis_rows;
         mpq big_number = m_abs_max.expt(3);
         mpq d = hnf_calc::determinant_of_rectangular_matrix(m_A, basis_rows, big_number);
         
-        //        std::cout << "max = " << m_abs_max << ", d = " << d << ", d/max = " << ceil (d /m_abs_max) << std::endl;
-        //std::cout << "max cube " << m_abs_max * m_abs_max * m_abs_max << std::endl;
+        // std::cout << "max = " << m_abs_max << ", d = " << d << ", d/max = " << ceil (d /m_abs_max) << std::endl;
+        // std::cout << "max cube " << m_abs_max * m_abs_max * m_abs_max << std::endl;
 
         if (d >= big_number) {
             return lia_move::undef;
         }
         
-        if (m_settings.get_cancel_flag())
+        if (m_settings.get_cancel_flag()) {
             return lia_move::undef;
+        }
+
         if (basis_rows.size() < m_A.row_count()) {
             m_A.shrink_to_rank(basis_rows);
             shrink_explanation(basis_rows);
         }
         
-        hnf<general_matrix> h(m_A, d);
-        //  general_matrix A_orig = m_A;
-        
+        hnf<general_matrix> h(m_A, d);        
         vector<mpq> b = create_b(basis_rows);
         lp_assert(m_A * x0 == b);
-        // vector<mpq> bcopy = b;
         find_h_minus_1_b(h.W(), b);
-        // lp_assert(bcopy == h.W().take_first_n_columns(b.size()) * b);
         int cut_row = find_cut_row_index(b);
-        if (cut_row == -1)
+
+        if (cut_row == -1) {
             return lia_move::undef;
+        }
+
         // the matrix is not square - we can get
         // all integers in b's projection
         
diff --git a/src/util/lp/int_solver.cpp b/src/util/lp/int_solver.cpp
index f49ecabfd..8bc2056b4 100644
--- a/src/util/lp/int_solver.cpp
+++ b/src/util/lp/int_solver.cpp
@@ -577,17 +577,27 @@ lia_move int_solver::make_hnf_cut() {
         return lia_move::undef;
     }
     settings().st().m_hnf_cutter_calls++;
-    TRACE("hnf_cut", tout << "settings().st().m_hnf_cutter_calls = " << settings().st().m_hnf_cutter_calls;);
+    TRACE("hnf_cut", tout << "settings().st().m_hnf_cutter_calls = " << settings().st().m_hnf_cutter_calls << "\n";
+          for (unsigned i : m_hnf_cutter.constraints_for_explanation()) {
+              m_lar_solver->print_constraint(i, tout);
+          }              
+          m_lar_solver->print_constraints(tout);
+          );
 #ifdef Z3DEBUG
     vector<mpq> x0 = m_hnf_cutter.transform_to_local_columns(m_lar_solver->m_mpq_lar_core_solver.m_r_x);
+#else
+    vector<mpq> x0;
 #endif
-    lia_move r =  m_hnf_cutter.create_cut(*m_t, *m_k, *m_ex, *m_upper
-#ifdef Z3DEBUG
-                                          , x0
-#endif
-                                          );
-    CTRACE("hnf_cut", r == lia_move::cut, tout<< "cut:"; m_lar_solver->print_term(*m_t, tout); tout << " <= " << *m_k << std::endl;);
-    if (r == lia_move::cut) {        
+    lia_move r =  m_hnf_cutter.create_cut(*m_t, *m_k, *m_ex, *m_upper, x0);
+
+    if (r == lia_move::cut) {      
+        TRACE("hnf_cut",
+              m_lar_solver->print_term(*m_t, tout << "cut:"); 
+              tout << " <= " << *m_k << std::endl;
+              for (unsigned i : m_hnf_cutter.constraints_for_explanation()) {
+                  m_lar_solver->print_constraint(i, tout);
+              }              
+              );
         lp_assert(current_solution_is_inf_on_cut());
         settings().st().m_hnf_cuts++;
         m_ex->clear();        

From 774fa33bfe050bc8f035290b794d7f838114bc2d Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Fri, 13 Jul 2018 08:49:46 -0700
Subject: [PATCH 04/10] fix parameter lookup

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/ast/seq_decl_plugin.cpp | 15 ++++++++-------
 1 file changed, 8 insertions(+), 7 deletions(-)

diff --git a/src/ast/seq_decl_plugin.cpp b/src/ast/seq_decl_plugin.cpp
index 00ba93ccb..07c6fd06a 100644
--- a/src/ast/seq_decl_plugin.cpp
+++ b/src/ast/seq_decl_plugin.cpp
@@ -363,12 +363,12 @@ bool seq_decl_plugin::is_sort_param(sort* s, unsigned& idx) {
 
 bool seq_decl_plugin::match(ptr_vector<sort>& binding, sort* s, sort* sP) {
     if (s == sP) return true;
-    unsigned i;
-    if (is_sort_param(sP, i)) {
-        if (binding.size() <= i) binding.resize(i+1);
-        if (binding[i] && (binding[i] != s)) return false;
-        TRACE("seq_verbose", tout << "setting binding @ " << i << " to " << mk_pp(s, *m_manager) << "\n";);
-        binding[i] = s;
+    unsigned idx;
+    if (is_sort_param(sP, idx)) {
+        if (binding.size() <= idx) binding.resize(idx+1);
+        if (binding[idx] && (binding[idx] != s)) return false;
+        TRACE("seq_verbose", tout << "setting binding @ " << idx << " to " << mk_pp(s, *m_manager) << "\n";);
+        binding[idx] = s;
         return true;
     }
 
@@ -376,7 +376,8 @@ bool seq_decl_plugin::match(ptr_vector<sort>& binding, sort* s, sort* sP) {
     if (s->get_family_id() == sP->get_family_id() &&
         s->get_decl_kind() == sP->get_decl_kind() &&
         s->get_num_parameters() == sP->get_num_parameters()) {
-        for (parameter const& p : s->parameters()) {
+		for (unsigned i = 0, sz = s->get_num_parameters(); i < sz; ++i) {
+			parameter const& p = s->get_parameter(i);
             if (p.is_ast() && is_sort(p.get_ast())) {
                 parameter const& p2 = sP->get_parameter(i);
                 if (!match(binding, to_sort(p.get_ast()), to_sort(p2.get_ast()))) return false;

From 88f4ce68fd46b2200c9d75d568eded5accc4c27f Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Fri, 13 Jul 2018 13:51:07 -0700
Subject: [PATCH 05/10] fix model generation regression exposed in nightly
 builds

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/smt/theory_lra.cpp | 12 +++++++++---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp
index ff5b72159..9c054830c 100644
--- a/src/smt/theory_lra.cpp
+++ b/src/smt/theory_lra.cpp
@@ -1118,7 +1118,7 @@ public:
             (v != null_theory_var) &&
             (v < static_cast<theory_var>(m_theory_var2var_index.size())) && 
             (UINT_MAX != m_theory_var2var_index[v]) &&
-            !m_variable_values.empty();
+            (!m_variable_values.empty() || m_solver->is_term(m_theory_var2var_index[v]));
     }
 
     bool can_get_bound(theory_var v) const {
@@ -1163,13 +1163,19 @@ public:
     }
         
     rational get_value(theory_var v) const {
-        if (!can_get_value(v)) return rational::zero();
+
+        if (v == null_theory_var || 
+            v >= static_cast<theory_var>(m_theory_var2var_index.size())) 
+            return rational::zero();
+            
         lp::var_index vi = m_theory_var2var_index[v];
         if (m_variable_values.count(vi) > 0)
             return m_variable_values[vi];
         
-        if(!m_solver->is_term(vi))
+        if (!m_solver->is_term(vi)) {
+            TRACE("arith", tout << "not a term v" << v << "\n";);
             return rational::zero();
+        }
         
         m_todo_terms.push_back(std::make_pair(vi, rational::one()));
         rational result(0);

From bdd8685146c91a159c5cb336d8dc439787eb49b7 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Fri, 13 Jul 2018 18:09:30 -0700
Subject: [PATCH 06/10] use params for arguments to Fixedpoint methods

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/api/dotnet/Fixedpoint.cs | 4 ++--
 src/smt/theory_lra.cpp       | 8 ++++++--
 2 files changed, 8 insertions(+), 4 deletions(-)

diff --git a/src/api/dotnet/Fixedpoint.cs b/src/api/dotnet/Fixedpoint.cs
index e2fb7fe5a..102a96ac5 100644
--- a/src/api/dotnet/Fixedpoint.cs
+++ b/src/api/dotnet/Fixedpoint.cs
@@ -146,7 +146,7 @@ namespace Microsoft.Z3
         /// The query is satisfiable if there is an instance of some relation that is non-empty.
         /// The query is unsatisfiable if there are no derivations satisfying any of the relations.
         /// </summary>        
-        public Status Query(FuncDecl[] relations)
+        public Status Query(params FuncDecl[] relations)
         {
             Contract.Requires(relations != null);
             Contract.Requires(Contract.ForAll(0, relations.Length, i => relations[i] != null));
@@ -262,7 +262,7 @@ namespace Microsoft.Z3
         /// <summary>
         /// Convert benchmark given as set of axioms, rules and queries to a string.
         /// </summary>                
-        public string ToString(BoolExpr[] queries)
+        public string ToString(params BoolExpr[] queries)
         {
 
             return Native.Z3_fixedpoint_to_string(Context.nCtx, NativeObject,
diff --git a/src/smt/theory_lra.cpp b/src/smt/theory_lra.cpp
index 9c054830c..ef1cd5f0a 100644
--- a/src/smt/theory_lra.cpp
+++ b/src/smt/theory_lra.cpp
@@ -1163,10 +1163,12 @@ public:
     }
         
     rational get_value(theory_var v) const {
-
+        
         if (v == null_theory_var || 
-            v >= static_cast<theory_var>(m_theory_var2var_index.size())) 
+            v >= static_cast<theory_var>(m_theory_var2var_index.size())) {
+            TRACE("arith", tout << "Variable v" << v << " not internalized\n";);
             return rational::zero();
+        }
             
         lp::var_index vi = m_theory_var2var_index[v];
         if (m_variable_values.count(vi) > 0)
@@ -1207,6 +1209,7 @@ public:
         if (!m.canceled() && m_solver.get() && th.get_num_vars() > 0) {
             reset_variable_values();
             m_solver->get_model(m_variable_values);
+            TRACE("arith", display(tout););
         }
     }
 
@@ -2642,6 +2645,7 @@ public:
         }
         else {
             rational r = get_value(v);
+            TRACE("arith", tout << "v" << v << " := " << r << "\n";);
             if (a.is_int(o) && !r.is_int()) r = floor(r);
             return alloc(expr_wrapper_proc, m_factory->mk_value(r,  m.get_sort(o)));
         }

From 7d20fbb28094f27e399d4d8cbc47bcee93f572f0 Mon Sep 17 00:00:00 2001
From: Nuno Lopes <nlopes@microsoft.com>
Date: Sat, 14 Jul 2018 12:21:43 +0100
Subject: [PATCH 07/10] do not cooperate if OMP mode is disabled (i.e. it's
 single threaded only)

---
 src/util/cooperate.cpp | 31 ++++---------------------------
 src/util/cooperate.h   | 19 ++++---------------
 src/util/mpq.h         |  3 ---
 3 files changed, 8 insertions(+), 45 deletions(-)

diff --git a/src/util/cooperate.cpp b/src/util/cooperate.cpp
index 2b2e7958e..df8f67968 100644
--- a/src/util/cooperate.cpp
+++ b/src/util/cooperate.cpp
@@ -16,6 +16,8 @@ Author:
 Notes:
 
 --*/
+
+#ifndef _NO_OMP_
 #include "util/cooperate.h"
 #include "util/trace.h"
 #include "util/debug.h"
@@ -36,7 +38,7 @@ struct cooperation_lock {
     }
 };
 
-cooperation_lock g_lock;
+static cooperation_lock g_lock;
 
 bool cooperation_ctx::g_cooperate = false;
 
@@ -59,29 +61,4 @@ void cooperation_ctx::checkpoint(char const * task) {
     }
 }
 
-cooperation_section::cooperation_section() {
-    SASSERT(!cooperation_ctx::enabled());
-    SASSERT(!omp_in_parallel());
-    cooperation_ctx::g_cooperate = true;
-}
-
-cooperation_section::~cooperation_section() {
-    SASSERT(cooperation_ctx::enabled());
-    cooperation_ctx::g_cooperate = false;
-}
-
-init_task::init_task(char const * task) {
-    SASSERT(cooperation_ctx::enabled());
-    SASSERT(omp_in_parallel());
-    cooperation_ctx::checkpoint(task);
-}
-
-init_task::~init_task() {
-    int  tid      = omp_get_thread_num();
-    if (g_lock.m_owner_thread == tid) {
-        g_lock.m_owner_thread = -1;
-        omp_unset_nest_lock(&(g_lock.m_lock));
-    }
-}
-
-
+#endif
diff --git a/src/util/cooperate.h b/src/util/cooperate.h
index af2cff55c..6220c4c51 100644
--- a/src/util/cooperate.h
+++ b/src/util/cooperate.h
@@ -19,10 +19,9 @@ Notes:
 #ifndef COOPERATE_H_
 #define COOPERATE_H_
 
-class cooperation_section;
+#ifndef _NO_OMP_
 
 class cooperation_ctx {
-    friend class cooperation_section;
     static bool g_cooperate;
 public:
     static bool enabled() { return g_cooperate; }
@@ -33,18 +32,8 @@ inline void cooperate(char const * task) {
     if (cooperation_ctx::enabled()) cooperation_ctx::checkpoint(task);
 }
 
-// must be declared before "#pragma parallel" to enable cooperation 
-class cooperation_section {
-public:
-    cooperation_section();
-    ~cooperation_section();
-};
-
-// must be first declaration inside "#pragma parallel for"
-class init_task {
-public:
-    init_task(char const * task);
-    ~init_task();
-};
+#else
+inline void cooperate(char const *) {}
+#endif
 
 #endif
diff --git a/src/util/mpq.h b/src/util/mpq.h
index b7bdbf400..77301371d 100644
--- a/src/util/mpq.h
+++ b/src/util/mpq.h
@@ -814,9 +814,6 @@ public:
     bool is_even(mpz const & a) { return mpz_manager<SYNCH>::is_even(a); }
 public:
     bool is_even(mpq const & a) { return is_int(a) && is_even(a.m_num); }
-
-    friend bool operator==(mpq const & a, mpq const & b) ;
-    friend bool operator>=(mpq const & a, mpq const & b);
 };
 
 typedef mpq_manager<true> synch_mpq_manager;

From b88596283ff4484a835601b49bee8599943fb179 Mon Sep 17 00:00:00 2001
From: Nuno Lopes <nlopes@microsoft.com>
Date: Sat, 14 Jul 2018 20:44:35 +0100
Subject: [PATCH 08/10] don't use mp[zq] synchronized mode if OpenMP mode is
 disabled

---
 src/util/mpff.cpp    | 10 ++++++++++
 src/util/mpff.h      | 19 ++++++++++++++++---
 src/util/mpfx.cpp    |  8 ++++++++
 src/util/mpfx.h      | 15 +++++++++++++--
 src/util/mpq.cpp     | 30 ++++++++++++++----------------
 src/util/mpq.h       | 44 ++++++++++++++++++++++++--------------------
 src/util/mpq_inf.cpp |  2 ++
 src/util/mpq_inf.h   |  4 ++++
 src/util/mpz.cpp     |  2 ++
 src/util/mpz.h       |  4 ++++
 10 files changed, 97 insertions(+), 41 deletions(-)

diff --git a/src/util/mpff.cpp b/src/util/mpff.cpp
index e00a25b1b..8ca2e983f 100644
--- a/src/util/mpff.cpp
+++ b/src/util/mpff.cpp
@@ -376,9 +376,11 @@ void mpff_manager::set(mpff & n, unsynch_mpz_manager & m, mpz const & v) {
     set_core(n, m, v); 
 }
 
+#ifndef _NO_OMP_
 void mpff_manager::set(mpff & n, synch_mpz_manager & m, mpz const & v) { 
     set_core(n, m, v); 
 }
+#endif
 
 template<bool SYNCH>
 void mpff_manager::set_core(mpff & n, mpq_manager<SYNCH> & m, mpq const & v) {
@@ -397,9 +399,11 @@ void mpff_manager::set(mpff & n, unsynch_mpq_manager & m, mpq const & v) {
     set_core(n, m, v); 
 }
 
+#ifndef _NO_OMP_
 void mpff_manager::set(mpff & n, synch_mpq_manager & m, mpq const & v) { 
     set_core(n, m, v); 
 }
+#endif
 
 bool mpff_manager::eq(mpff const & a, mpff const & b) const {
     if (is_zero(a) && is_zero(b))
@@ -1077,9 +1081,11 @@ void mpff_manager::significand(mpff const & n, unsynch_mpz_manager & m, mpz & t)
     significand_core(n, m, t);
 }
 
+#ifndef _NO_OMP_
 void mpff_manager::significand(mpff const & n, synch_mpz_manager & m, mpz & t) {
     significand_core(n, m, t);
 }
+#endif
 
 template<bool SYNCH>
 void mpff_manager::to_mpz_core(mpff const & n, mpz_manager<SYNCH> & m, mpz & t) {
@@ -1109,9 +1115,11 @@ void mpff_manager::to_mpz(mpff const & n, unsynch_mpz_manager & m, mpz & t) {
     to_mpz_core(n, m, t);
 }
 
+#ifndef _NO_OMP_
 void mpff_manager::to_mpz(mpff const & n, synch_mpz_manager & m, mpz & t) {
     to_mpz_core(n, m, t);
 }
+#endif
 
 template<bool SYNCH>
 void mpff_manager::to_mpq_core(mpff const & n, mpq_manager<SYNCH> & m, mpq & t) {
@@ -1154,9 +1162,11 @@ void mpff_manager::to_mpq(mpff const & n, unsynch_mpq_manager & m, mpq & t) {
     to_mpq_core(n, m, t);
 }
 
+#ifndef _NO_OMP_
 void mpff_manager::to_mpq(mpff const & n, synch_mpq_manager & m, mpq & t) {
     to_mpq_core(n, m, t);
 }
+#endif
 
 void mpff_manager::display_raw(std::ostream & out, mpff const & n) const {
     if (is_neg(n))
diff --git a/src/util/mpff.h b/src/util/mpff.h
index 8023053d2..6f1e9d23c 100644
--- a/src/util/mpff.h
+++ b/src/util/mpff.h
@@ -58,9 +58,14 @@ class mpz;
 class mpq;
 template<bool SYNCH> class mpz_manager;
 template<bool SYNCH> class mpq_manager;
+#ifndef _NO_OMP_
 typedef mpz_manager<true>  synch_mpz_manager;
-typedef mpz_manager<false> unsynch_mpz_manager;
 typedef mpq_manager<true>  synch_mpq_manager;
+#else
+typedef mpz_manager<false>  synch_mpz_manager;
+typedef mpq_manager<false>  synch_mpq_manager;
+#endif
+typedef mpz_manager<false> unsynch_mpz_manager;
 typedef mpq_manager<false> unsynch_mpq_manager;
 
 class mpff_manager {
@@ -213,7 +218,9 @@ public:
        \brief Return the significand as a mpz numeral.
     */
     void significand(mpff const & n, unsynch_mpz_manager & m, mpz & r);
+#ifndef _NO_OMP_
     void significand(mpff const & n, synch_mpz_manager & m, mpz & r);
+#endif
 
     /**
        \brief Return true if n is negative
@@ -378,9 +385,11 @@ public:
     void set(mpff & n, int64_t num, uint64_t den);
     void set(mpff & n, mpff const & v);
     void set(mpff & n, unsynch_mpz_manager & m, mpz const & v);
-    void set(mpff & n, synch_mpz_manager & m, mpz const & v); 
     void set(mpff & n, unsynch_mpq_manager & m, mpq const & v);
+#ifndef _NO_OMP_
     void set(mpff & n, synch_mpq_manager & m, mpq const & v);
+    void set(mpff & n, synch_mpz_manager & m, mpz const & v);
+#endif
     void set_plus_epsilon(mpff & n);
     void set_minus_epsilon(mpff & n);
     void set_max(mpff & n);
@@ -420,6 +429,7 @@ public:
     */
     void to_mpz(mpff const & n, unsynch_mpz_manager & m, mpz & t);
 
+#ifndef _NO_OMP_
     /**
        \brief Convert n into a mpz numeral.
        
@@ -428,6 +438,7 @@ public:
        \remark if exponent(n) is too big, we may run out of memory.
     */
     void to_mpz(mpff const & n, synch_mpz_manager & m, mpz & t);
+#endif
 
     /**
        \brief Convert n into a mpq numeral.
@@ -436,13 +447,15 @@ public:
     */
     void to_mpq(mpff const & n, unsynch_mpq_manager & m, mpq & t);
 
+#ifndef _NO_OMP_
     /**
        \brief Convert n into a mpq numeral.
 
        \remark if exponent(n) is too big, we may run out of memory.
     */
     void to_mpq(mpff const & n, synch_mpq_manager & m, mpq & t);
-    
+#endif
+
     /**
        \brief Return n as an int64.
 
diff --git a/src/util/mpfx.cpp b/src/util/mpfx.cpp
index 2ebc54840..8ed16ec68 100644
--- a/src/util/mpfx.cpp
+++ b/src/util/mpfx.cpp
@@ -272,9 +272,11 @@ void mpfx_manager::set(mpfx & n, unsynch_mpz_manager & m, mpz const & v) {
     set_core(n, m, v);
 }
 
+#ifndef _NO_OMP_
 void mpfx_manager::set(mpfx & n, synch_mpz_manager & m, mpz const & v) {
     set_core(n, m, v);
 }
+#endif
 
 template<bool SYNCH>
 void mpfx_manager::set_core(mpfx & n, mpq_manager<SYNCH> & m, mpq const & v) {
@@ -309,9 +311,11 @@ void mpfx_manager::set(mpfx & n, unsynch_mpq_manager & m, mpq const & v) {
     set_core(n, m, v);
 }
 
+#ifndef _NO_OMP_
 void mpfx_manager::set(mpfx & n, synch_mpq_manager & m, mpq const & v) {
     set_core(n, m, v);
 }
+#endif
 
 bool mpfx_manager::eq(mpfx const & a, mpfx const & b) const {
     if (is_zero(a) && is_zero(b))
@@ -714,9 +718,11 @@ void mpfx_manager::to_mpz(mpfx const & n, unsynch_mpz_manager & m, mpz & t) {
     to_mpz_core(n, m, t);
 }
 
+#ifndef _NO_OMP_
 void mpfx_manager::to_mpz(mpfx const & n, synch_mpz_manager & m, mpz & t) {
     to_mpz_core(n, m, t);
 }
+#endif
 
 template<bool SYNCH>
 void mpfx_manager::to_mpq_core(mpfx const & n, mpq_manager<SYNCH> & m, mpq & t) {
@@ -738,9 +744,11 @@ void mpfx_manager::to_mpq(mpfx const & n, unsynch_mpq_manager & m, mpq & t) {
     to_mpq_core(n, m, t);
 }
 
+#ifndef _NO_OMP_
 void mpfx_manager::to_mpq(mpfx const & n, synch_mpq_manager & m, mpq & t) {
     to_mpq_core(n, m, t);
 }
+#endif
 
 void mpfx_manager::display_raw(std::ostream & out, mpfx const & n) const {
     if (is_neg(n))
diff --git a/src/util/mpfx.h b/src/util/mpfx.h
index a8e93f0b0..6de3f251b 100644
--- a/src/util/mpfx.h
+++ b/src/util/mpfx.h
@@ -51,9 +51,14 @@ class mpz;
 class mpq;
 template<bool SYNCH> class mpz_manager;
 template<bool SYNCH> class mpq_manager;
+#ifndef _NO_OMP_
 typedef mpz_manager<true>  synch_mpz_manager;
-typedef mpz_manager<false> unsynch_mpz_manager;
 typedef mpq_manager<true>  synch_mpq_manager;
+#else
+typedef mpz_manager<false>  synch_mpz_manager;
+typedef mpq_manager<false>  synch_mpq_manager;
+#endif
+typedef mpz_manager<false> unsynch_mpz_manager;
 typedef mpq_manager<false> unsynch_mpq_manager;
 
 class mpfx_manager {
@@ -312,9 +317,11 @@ public:
     void set(mpfx & n, int64_t num, uint64_t den);
     void set(mpfx & n, mpfx const & v);
     void set(mpfx & n, unsynch_mpz_manager & m, mpz const & v);
-    void set(mpfx & n, synch_mpz_manager & m, mpz const & v); 
     void set(mpfx & n, unsynch_mpq_manager & m, mpq const & v);
+#ifndef _NO_OMP_
+    void set(mpfx & n, synch_mpz_manager & m, mpz const & v);
     void set(mpfx & n, synch_mpq_manager & m, mpq const & v);
+#endif
 
     /** 
         \brief Set n to the smallest representable numeral greater than zero.
@@ -359,22 +366,26 @@ public:
     */
     void to_mpz(mpfx const & n, unsynch_mpz_manager & m, mpz & t);
 
+#ifndef _NO_OMP_
     /**
        \brief Convert n into a mpz numeral.
        
        \pre is_int(n)
     */
     void to_mpz(mpfx const & n, synch_mpz_manager & m, mpz & t);
+#endif
 
     /**
        \brief Convert n into a mpq numeral.
     */
     void to_mpq(mpfx const & n, unsynch_mpq_manager & m, mpq & t);
 
+#ifndef _NO_OMP_
     /**
        \brief Convert n into a mpq numeral.
     */
     void to_mpq(mpfx const & n, synch_mpq_manager & m, mpq & t);
+#endif
 
     /**
        \brief Return the biggest k s.t. 2^k <= a.
diff --git a/src/util/mpq.cpp b/src/util/mpq.cpp
index 30ac0f410..207614ee0 100644
--- a/src/util/mpq.cpp
+++ b/src/util/mpq.cpp
@@ -26,12 +26,12 @@ mpq_manager<SYNCH>::mpq_manager() {
 
 template<bool SYNCH>
 mpq_manager<SYNCH>::~mpq_manager() {
-    del(m_n_tmp);
-    del(m_add_tmp1);
-    del(m_add_tmp2);
-    del(m_lt_tmp1);
-    del(m_lt_tmp2);
-    del(m_addmul_tmp);
+    del(m_tmp1);
+    del(m_tmp2);
+    del(m_tmp3);
+    del(m_tmp4);
+    del(m_q_tmp1);
+    del(m_q_tmp2);
 }
 
 
@@ -68,9 +68,9 @@ bool mpq_manager<SYNCH>::rat_lt(mpq const & a, mpq const & b) {
         return r;
     }
     else {
-        mul(na, db, m_lt_tmp1);
-        mul(nb, da, m_lt_tmp2);
-        return lt(m_lt_tmp1, m_lt_tmp2);
+        mul(na, db, m_q_tmp1);
+        mul(nb, da, m_q_tmp2);
+        return lt(m_q_tmp1, m_q_tmp2);
     }
 }
 
@@ -384,8 +384,7 @@ void mpq_manager<SYNCH>::rat_mul(mpq const & a, mpq const & b, mpq & c) {
         del(tmp2);
     }
     else {
-        mpz& g1 = m_n_tmp, &g2 = m_addmul_tmp.m_num, &tmp1 = m_add_tmp1, &tmp2 = m_add_tmp2;
-        rat_mul(a, b, c, g1, g2, tmp1, tmp2);
+        rat_mul(a, b, c, m_tmp1, m_tmp2, m_tmp3, m_tmp4);
     }
     STRACE("rat_mpq", tout << to_string(c) << "\n";);
 }
@@ -402,8 +401,7 @@ void mpq_manager<SYNCH>::rat_add(mpq const & a, mpq const & b, mpq & c) {
         del(g);
     }
     else {
-        mpz& g = m_n_tmp, &tmp1 = m_add_tmp1, &tmp2 = m_add_tmp2, &tmp3 = m_addmul_tmp.m_num;
-        lin_arith_op<false>(a, b, c, g, tmp1, tmp2, tmp3);
+        lin_arith_op<false>(a, b, c, m_tmp1, m_tmp2, m_tmp3, m_tmp4);
     }
     STRACE("rat_mpq", tout << to_string(c) << "\n";);
 }
@@ -420,13 +418,13 @@ void mpq_manager<SYNCH>::rat_sub(mpq const & a, mpq const & b, mpq & c) {
         del(g);
     }
     else {
-        mpz& g = m_n_tmp, &tmp1 = m_add_tmp1, &tmp2 = m_add_tmp2, &tmp3 = m_addmul_tmp.m_num;
-        lin_arith_op<true>(a, b, c, g, tmp1, tmp2, tmp3);
+        lin_arith_op<true>(a, b, c, m_tmp1, m_tmp2, m_tmp3, m_tmp4);
     }
     STRACE("rat_mpq", tout << to_string(c) << "\n";);
 }
 
 
+#ifndef _NO_OMP_
 template class mpq_manager<true>;
+#endif
 template class mpq_manager<false>;
-
diff --git a/src/util/mpq.h b/src/util/mpq.h
index 77301371d..20802f786 100644
--- a/src/util/mpq.h
+++ b/src/util/mpq.h
@@ -41,12 +41,12 @@ inline void swap(mpq & m1, mpq & m2) { m1.swap(m2); }
 
 template<bool SYNCH = true>
 class mpq_manager : public mpz_manager<SYNCH> {
-    mpz m_n_tmp;
-    mpz m_add_tmp1;
-    mpz m_add_tmp2;
-    mpq m_addmul_tmp;
-    mpq m_lt_tmp1;
-    mpq m_lt_tmp2;
+    mpz m_tmp1;
+    mpz m_tmp2;
+    mpz m_tmp3;
+    mpz m_tmp4;
+    mpq m_q_tmp1;
+    mpq m_q_tmp2;
 
     void reset_denominator(mpq & a) {
         del(a.m_den);
@@ -66,11 +66,11 @@ class mpq_manager : public mpz_manager<SYNCH> {
             del(tmp);
         }
         else {
-            gcd(a.m_num, a.m_den, m_n_tmp);
-            if (is_one(m_n_tmp))
+            gcd(a.m_num, a.m_den, m_tmp1);
+            if (is_one(m_tmp1))
                 return;
-            div(a.m_num, m_n_tmp, a.m_num);
-            div(a.m_den, m_n_tmp, a.m_den);
+            div(a.m_num, m_tmp1, a.m_num);
+            div(a.m_den, m_tmp1, a.m_den);
         }
     }
 
@@ -87,9 +87,9 @@ class mpq_manager : public mpz_manager<SYNCH> {
             del(tmp1);
         }
         else {
-            mul(b, a.m_den, m_add_tmp1);
+            mul(b, a.m_den, m_tmp1);
             set(c.m_den, a.m_den);
-            add(a.m_num, m_add_tmp1, c.m_num);
+            add(a.m_num, m_tmp1, c.m_num);
             normalize(c);
         }
         STRACE("rat_mpq", tout << to_string(c) << "\n";);
@@ -320,8 +320,8 @@ public:
                 del(tmp);
             }
             else {
-                mul(b,c,m_addmul_tmp);
-                add(a, m_addmul_tmp, d);
+                mul(b, c, m_q_tmp1);
+                add(a, m_q_tmp1, d);
             }
         }
     }
@@ -342,8 +342,8 @@ public:
                 del(tmp);
             }
             else {
-                mul(b,c,m_addmul_tmp);
-                add(a, m_addmul_tmp, d);
+                mul(b,c, m_q_tmp1);
+                add(a, m_q_tmp1, d);
             }
         }
     }
@@ -365,8 +365,8 @@ public:
                 del(tmp);
             }
             else {
-                mul(b,c,m_addmul_tmp);
-                sub(a, m_addmul_tmp, d);
+                mul(b,c, m_q_tmp1);
+                sub(a, m_q_tmp1, d);
             }
         }
     }
@@ -387,8 +387,8 @@ public:
                 del(tmp);
             }
             else {
-                mul(b,c,m_addmul_tmp);
-                sub(a, m_addmul_tmp, d);
+                mul(b,c, m_q_tmp1);
+                sub(a, m_q_tmp1, d);
             }
         }
     }
@@ -816,7 +816,11 @@ public:
     bool is_even(mpq const & a) { return is_int(a) && is_even(a.m_num); }
 };
 
+#ifndef _NO_OMP_
 typedef mpq_manager<true> synch_mpq_manager;
+#else
+typedef mpq_manager<false> synch_mpq_manager;
+#endif
 typedef mpq_manager<false> unsynch_mpq_manager;
 
 typedef _scoped_numeral<unsynch_mpq_manager> scoped_mpq;
diff --git a/src/util/mpq_inf.cpp b/src/util/mpq_inf.cpp
index c6c160941..69de425cf 100644
--- a/src/util/mpq_inf.cpp
+++ b/src/util/mpq_inf.cpp
@@ -39,5 +39,7 @@ std::string mpq_inf_manager<SYNCH>::to_string(mpq_inf const & a) {
 }
 
 
+#ifndef _NO_OMP_
 template class mpq_inf_manager<true>;
+#endif
 template class mpq_inf_manager<false>;
diff --git a/src/util/mpq_inf.h b/src/util/mpq_inf.h
index 7b866994d..c7bd261e6 100644
--- a/src/util/mpq_inf.h
+++ b/src/util/mpq_inf.h
@@ -279,7 +279,11 @@ public:
     mpq_manager<SYNCH>& get_mpq_manager() { return m; }
 };
 
+#ifndef _NO_OMP_
 typedef mpq_inf_manager<true>  synch_mpq_inf_manager;
+#else
+typedef mpq_inf_manager<false> synch_mpq_inf_manager;
+#endif
 typedef mpq_inf_manager<false> unsynch_mpq_inf_manager;
 
 #endif
diff --git a/src/util/mpz.cpp b/src/util/mpz.cpp
index 7ad4797b7..32a074eb3 100644
--- a/src/util/mpz.cpp
+++ b/src/util/mpz.cpp
@@ -2369,5 +2369,7 @@ bool mpz_manager<SYNCH>::divides(mpz const & a, mpz const & b) {
     return r;
 }
 
+#ifndef _NO_OMP_
 template class mpz_manager<true>;
+#endif
 template class mpz_manager<false>;
diff --git a/src/util/mpz.h b/src/util/mpz.h
index f480b097e..187532a87 100644
--- a/src/util/mpz.h
+++ b/src/util/mpz.h
@@ -692,7 +692,11 @@ public:
     bool decompose(mpz const & n, svector<digit_t> & digits);
 };
 
+#ifndef _NO_OMP_
 typedef mpz_manager<true> synch_mpz_manager;
+#else
+typedef mpz_manager<false> synch_mpz_manager;
+#endif
 typedef mpz_manager<false> unsynch_mpz_manager;
 
 typedef _scoped_numeral<unsynch_mpz_manager> scoped_mpz;

From dfa8c4432fed9e1c47b32681c3fcda0389b58ae2 Mon Sep 17 00:00:00 2001
From: Nuno Lopes <nlopes@microsoft.com>
Date: Sat, 14 Jul 2018 20:50:49 +0100
Subject: [PATCH 09/10] add parameter(rational&&)

---
 src/ast/ast.h | 1 +
 1 file changed, 1 insertion(+)

diff --git a/src/ast/ast.h b/src/ast/ast.h
index 364be8a77..89df04961 100644
--- a/src/ast/ast.h
+++ b/src/ast/ast.h
@@ -122,6 +122,7 @@ public:
     explicit parameter(ast * p): m_kind(PARAM_AST), m_ast(p) {}
     explicit parameter(symbol const & s): m_kind(PARAM_SYMBOL), m_symbol(s.c_ptr()) {}
     explicit parameter(rational const & r): m_kind(PARAM_RATIONAL), m_rational(alloc(rational, r)) {}
+    explicit parameter(rational && r) : m_kind(PARAM_RATIONAL), m_rational(alloc(rational, std::move(r))) {}
     explicit parameter(double d):m_kind(PARAM_DOUBLE), m_dval(d) {}
     explicit parameter(const char *s):m_kind(PARAM_SYMBOL), m_symbol(symbol(s).c_ptr()) {}
     explicit parameter(unsigned ext_id, bool):m_kind(PARAM_EXTERNAL), m_ext_id(ext_id) {}

From f7ac0966965781eda14e468bfba672c9f741490f Mon Sep 17 00:00:00 2001
From: Lev Nachmanson <levnach@hotmail.com>
Date: Sun, 15 Jul 2018 15:29:13 -0700
Subject: [PATCH 10/10] avoid a vector copy

Signed-off-by: Lev Nachmanson <levnach@hotmail.com>
---
 src/util/lp/lar_solver.h | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/util/lp/lar_solver.h b/src/util/lp/lar_solver.h
index 72705dfb3..3735fbb9f 100644
--- a/src/util/lp/lar_solver.h
+++ b/src/util/lp/lar_solver.h
@@ -112,7 +112,7 @@ private:
     
 public :
     unsigned terms_start_index() const { return m_terms_start_index; }
-    const vector<lar_term*> terms() const { return m_terms; }
+    const vector<lar_term*> & terms() const { return m_terms; }
     const vector<lar_base_constraint*>& constraints() const {
         return m_constraints;
     }