From 706a037bf4bc20e37f85978b6ae8912cb9f32e67 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 16 Nov 2015 15:16:50 +0100
Subject: [PATCH 01/14] Python 3.x string decoding fix

---
 scripts/update_api.py       | 2 +-
 src/api/python/z3printer.py | 8 +++++++-
 2 files changed, 8 insertions(+), 2 deletions(-)

diff --git a/scripts/update_api.py b/scripts/update_api.py
index bb5935a1e..6e7b6d5f7 100644
--- a/scripts/update_api.py
+++ b/scripts/update_api.py
@@ -99,7 +99,7 @@ else:
      if s != None:
         enc = sys.stdout.encoding
         if enc != None: return s.decode(enc)
-        else: return s
+        else: return s.decode('ascii')
      else:
         return ""
 
diff --git a/src/api/python/z3printer.py b/src/api/python/z3printer.py
index 5116046dd..2a242865e 100644
--- a/src/api/python/z3printer.py
+++ b/src/api/python/z3printer.py
@@ -1157,7 +1157,13 @@ def set_pp_option(k, v):
 def obj_to_string(a):
     out = io.StringIO()
     _PP(out, _Formatter(a))
-    return out.getvalue()
+    r = out.getvalue()
+    if sys.version < '3':
+        return r
+    else:
+        enc = sys.stdout.encoding
+        if enc != None: return r.decode(enc)
+        return r
 
 _html_out = None
 

From e8d37dba9cce90574ed5c9ad640968c0362c5c82 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Mon, 16 Nov 2015 21:58:17 +0100
Subject: [PATCH 02/14] Added comments for quantifier constructors. Fixes #319.

---
 src/api/dotnet/Context.cs | 26 ++++++++++++++++--
 src/api/java/Context.java | 58 +++++++++++++++++++++++----------------
 2 files changed, 57 insertions(+), 27 deletions(-)

diff --git a/src/api/dotnet/Context.cs b/src/api/dotnet/Context.cs
index 25c399d68..d56ba4af1 100644
--- a/src/api/dotnet/Context.cs
+++ b/src/api/dotnet/Context.cs
@@ -2613,8 +2613,13 @@ namespace Microsoft.Z3
         /// <paramref name="patterns"/> is an array of patterns, <paramref name="sorts"/> is an array
         /// with the sorts of the bound variables, <paramref name="names"/> is an array with the
         /// 'names' of the bound variables, and <paramref name="body"/> is the body of the
-        /// quantifier. Quantifiers are associated with weights indicating
-        /// the importance of using the quantifier during instantiation.
+        /// quantifier. Quantifiers are associated with weights indicating the importance of 
+        /// using the quantifier during instantiation.
+        /// Note that the bound variables are de-Bruijn indices created using <see cref="MkBound"/>. 
+        /// Z3 applies the convention that the last element in <paramref name="names"/> and 
+        /// <paramref name="sorts"/> refers to the variable with index 0, the second to last element 
+        /// of <paramref name="names"/> and <paramref name="sorts"/> refers to the variable 
+        /// with index 1, etc. 
         /// </remarks>
         /// <param name="sorts">the sorts of the bound variables.</param>
         /// <param name="names">names of the bound variables</param>
@@ -2644,6 +2649,11 @@ namespace Microsoft.Z3
         /// <summary>
         /// Create a universal Quantifier.
         /// </summary>
+        /// <remarks>
+        /// Creates a universal quantifier using a list of constants that will 
+        /// form the set of bound variables. 
+        /// <seealso cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
+        /// </remarks>
         public Quantifier MkForall(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
         {
             Contract.Requires(body != null);
@@ -2659,7 +2669,10 @@ namespace Microsoft.Z3
         /// <summary>
         /// Create an existential Quantifier.
         /// </summary>
-        /// <seealso cref="MkForall(Sort[],Symbol[],Expr,uint,Pattern[],Expr[],Symbol,Symbol)"/>
+        /// <remarks>
+        /// Creates an existential quantifier using de-Brujin indexed variables. 
+        /// (<see cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>).
+        /// </remarks>
         public Quantifier MkExists(Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
         {
             Contract.Requires(sorts != null);
@@ -2678,6 +2691,11 @@ namespace Microsoft.Z3
         /// <summary>
         /// Create an existential Quantifier.
         /// </summary>
+        /// <remarks>
+        /// Creates an existential quantifier using a list of constants that will 
+        /// form the set of bound variables. 
+        /// <seealso cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
+        /// </remarks>
         public Quantifier MkExists(Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
         {
             Contract.Requires(body != null);
@@ -2693,6 +2711,7 @@ namespace Microsoft.Z3
         /// <summary>
         /// Create a Quantifier.
         /// </summary>
+        /// <see cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
         public Quantifier MkQuantifier(bool universal, Sort[] sorts, Symbol[] names, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
         {
             Contract.Requires(body != null);
@@ -2716,6 +2735,7 @@ namespace Microsoft.Z3
         /// <summary>
         /// Create a Quantifier.
         /// </summary>
+        /// <see cref="MkForall(Sort[], Symbol[], Expr, uint, Pattern[], Expr[], Symbol, Symbol)"/>
         public Quantifier MkQuantifier(bool universal, Expr[] boundConstants, Expr body, uint weight = 1, Pattern[] patterns = null, Expr[] noPatterns = null, Symbol quantifierID = null, Symbol skolemID = null)
         {
             Contract.Requires(body != null);
diff --git a/src/api/java/Context.java b/src/api/java/Context.java
index 0f9a85799..4d8484ced 100644
--- a/src/api/java/Context.java
+++ b/src/api/java/Context.java
@@ -433,8 +433,8 @@ public class Context extends IDisposable
     /**
      * Creates a fresh function declaration with a name prefixed with
      * {@code prefix}. 
-     * @see mkFuncDecl(String,Sort,Sort)
-     * @see mkFuncDecl(String,Sort[],Sort)
+     * @see #mkFuncDecl(String,Sort,Sort)
+     * @see #mkFuncDecl(String,Sort[],Sort)
      **/
     public FuncDecl mkFreshFuncDecl(String prefix, Sort[] domain, Sort range)
            
@@ -1722,9 +1722,9 @@ public class Context extends IDisposable
      **/
     public Expr mkArrayExt(ArrayExpr arg1, ArrayExpr arg2)
     {
-	checkContextMatch(arg1);
-	checkContextMatch(arg2);
-	return Expr.create(this, Native.mkArrayExt(nCtx(), arg1.getNativeObject(), arg2.getNativeObject()));
+    checkContextMatch(arg1);
+    checkContextMatch(arg2);
+    return Expr.create(this, Native.mkArrayExt(nCtx(), arg1.getNativeObject(), arg2.getNativeObject()));
     }
 
 
@@ -2025,6 +2025,7 @@ public class Context extends IDisposable
 
     /**
      * Create a universal Quantifier.
+     *
      * @param sorts the sorts of the bound variables. 
      * @param names names of the bound variables 
      * @param body the body of the quantifier. 
@@ -2034,17 +2035,22 @@ public class Context extends IDisposable
      * @param quantifierID optional symbol to track quantifier. 
      * @param skolemID optional symbol to track skolem constants.
      * 
-     * Remarks:  Creates a forall formula, where
-     * {@code weight"/> is the weight, <paramref name="patterns} is
+     * @return Creates a forall formula, where
+     * {@code weight} is the weight, {@code patterns} is
      * an array of patterns, {@code sorts} is an array with the sorts
      * of the bound variables, {@code names} is an array with the
      * 'names' of the bound variables, and {@code body} is the body
      * of the quantifier. Quantifiers are associated with weights indicating the
      * importance of using the quantifier during instantiation.
+     * Note that the bound variables are de-Bruijn indices created using {@link mkBound}.
+     * Z3 applies the convention that the last element in {@code names} and 
+     * {@code sorts} refers to the variable with index 0, the second to last element 
+     * of {@code names} and {@code sorts} refers to the variable 
+     * with index 1, etc. 
      **/
     public Quantifier mkForall(Sort[] sorts, Symbol[] names, Expr body,
-            int weight, Pattern[] patterns, Expr[] noPatterns,
-            Symbol quantifierID, Symbol skolemID)
+                               int weight, Pattern[] patterns, Expr[] noPatterns,
+                               Symbol quantifierID, Symbol skolemID)
     {
 
         return new Quantifier(this, true, sorts, names, body, weight, patterns,
@@ -2052,11 +2058,12 @@ public class Context extends IDisposable
     }
 
     /**
-     * Create a universal Quantifier.
+     * Creates a universal quantifier using a list of constants that will form the set of bound variables. 
+     * @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
      **/
     public Quantifier mkForall(Expr[] boundConstants, Expr body, int weight,
-            Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
-            Symbol skolemID)
+                               Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
+                               Symbol skolemID)
     {
 
         return new Quantifier(this, true, boundConstants, body, weight,
@@ -2064,12 +2071,12 @@ public class Context extends IDisposable
     }
 
     /**
-     * Create an existential Quantifier. 
+     * Creates an existential quantifier using de-Brujin indexed variables. 
      * @see mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
      **/
     public Quantifier mkExists(Sort[] sorts, Symbol[] names, Expr body,
-            int weight, Pattern[] patterns, Expr[] noPatterns,
-            Symbol quantifierID, Symbol skolemID)
+                               int weight, Pattern[] patterns, Expr[] noPatterns,
+                               Symbol quantifierID, Symbol skolemID)
     {
 
         return new Quantifier(this, false, sorts, names, body, weight,
@@ -2077,11 +2084,12 @@ public class Context extends IDisposable
     }
 
     /**
-     * Create an existential Quantifier.
+     * Creates an existential quantifier using a list of constants that will form the set of bound variables. 
+     * @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
      **/
     public Quantifier mkExists(Expr[] boundConstants, Expr body, int weight,
-            Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
-            Symbol skolemID)
+                               Pattern[] patterns, Expr[] noPatterns, Symbol quantifierID,
+                               Symbol skolemID)
     {
 
         return new Quantifier(this, false, boundConstants, body, weight,
@@ -2090,11 +2098,12 @@ public class Context extends IDisposable
 
     /**
      * Create a Quantifier.
+     * @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
      **/
     public Quantifier mkQuantifier(boolean universal, Sort[] sorts,
-            Symbol[] names, Expr body, int weight, Pattern[] patterns,
-            Expr[] noPatterns, Symbol quantifierID, Symbol skolemID)
-           
+                                   Symbol[] names, Expr body, int weight, Pattern[] patterns,
+                                   Expr[] noPatterns, Symbol quantifierID, Symbol skolemID)
+        
     {
 
         if (universal)
@@ -2106,11 +2115,12 @@ public class Context extends IDisposable
     }
 
     /**
-     * Create a Quantifier.
+     * Create a Quantifier
+     * @see #mkForall(Sort[],Symbol[],Expr,int,Pattern[],Expr[],Symbol,Symbol)
      **/
     public Quantifier mkQuantifier(boolean universal, Expr[] boundConstants,
-            Expr body, int weight, Pattern[] patterns, Expr[] noPatterns,
-            Symbol quantifierID, Symbol skolemID)
+                                   Expr body, int weight, Pattern[] patterns, Expr[] noPatterns,
+                                   Symbol quantifierID, Symbol skolemID)
     {
 
         if (universal)

From 4e9b76365d40882318c32e64682b96e80415b95a Mon Sep 17 00:00:00 2001
From: Yan <yans@yancomm.net>
Date: Mon, 16 Nov 2015 15:41:12 -0800
Subject: [PATCH 03/14] pass the correct context into And() when doing
 Tactic.as_expr()

---
 src/api/python/z3.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/api/python/z3.py b/src/api/python/z3.py
index 214d8b687..444c025e6 100644
--- a/src/api/python/z3.py
+++ b/src/api/python/z3.py
@@ -4862,7 +4862,7 @@ class Goal(Z3PPObject):
         elif sz == 1:
             return self.get(0)
         else:
-            return And([ self.get(i) for i in range(len(self)) ])
+            return And([ self.get(i) for i in range(len(self)) ], self.ctx)
 
 #########################################
 #

From c8f09fa955ce4f6bb259eea03697db8944c9cd2f Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Mon, 16 Nov 2015 22:59:07 -0800
Subject: [PATCH 04/14] fix for unsound results reported in #313

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/ast/ast_util.cpp        |  9 ++++++
 src/ast/ast_util.h          |  7 +++++
 src/muz/pdr/pdr_context.cpp | 61 +++++++++++++++++++++++--------------
 src/muz/pdr/pdr_context.h   |  1 -
 4 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/src/ast/ast_util.cpp b/src/ast/ast_util.cpp
index 94e7b642c..eba4d526b 100644
--- a/src/ast/ast_util.cpp
+++ b/src/ast/ast_util.cpp
@@ -166,6 +166,11 @@ expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args) {
         return m.mk_and(num_args, args);
 }
 
+app* mk_and(ast_manager & m, unsigned num_args, app * const * args) {
+    return to_app(mk_and(m, num_args, (expr* const*) args));
+}
+
+
 expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
     if (num_args == 0)
         return m.mk_false();
@@ -175,6 +180,10 @@ expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
         return m.mk_or(num_args, args);
 }
 
+app* mk_or(ast_manager & m, unsigned num_args, app * const * args) {
+    return to_app(mk_or(m, num_args, (expr* const*) args));
+}
+
 expr * mk_not(ast_manager & m, expr * arg) {
     expr * atom;
     if (m.is_not(arg, atom))
diff --git a/src/ast/ast_util.h b/src/ast/ast_util.h
index 87a3a90d9..311001a19 100644
--- a/src/ast/ast_util.h
+++ b/src/ast/ast_util.h
@@ -107,6 +107,9 @@ expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx);
    Return true                               if num_args == 0
  */
 expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
+app  * mk_and(ast_manager & m, unsigned num_args, app * const * args);
+inline app_ref mk_and(app_ref_vector const& args) { return app_ref(mk_and(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
+inline expr_ref mk_and(expr_ref_vector const& args) { return expr_ref(mk_and(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
 
 /**
    Return (or args[0] ... args[num_args-1]) if num_args >= 2
@@ -114,6 +117,10 @@ expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
    Return false                             if num_args == 0
  */
 expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args);
+app  * mk_or(ast_manager & m, unsigned num_args, app * const * args);
+inline app_ref mk_or(app_ref_vector const& args) { return app_ref(mk_or(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
+inline expr_ref mk_or(expr_ref_vector const& args) { return expr_ref(mk_or(args.get_manager(), args.size(), args.c_ptr()), args.get_manager()); }
+
 
 /**
    Return a          if arg = (not a)
diff --git a/src/muz/pdr/pdr_context.cpp b/src/muz/pdr/pdr_context.cpp
index 4cdc76ede..5140c9eff 100644
--- a/src/muz/pdr/pdr_context.cpp
+++ b/src/muz/pdr/pdr_context.cpp
@@ -50,6 +50,7 @@ Notes:
 #include "blast_term_ite_tactic.h"
 #include "model_implicant.h"
 #include "expr_safe_replace.h"
+#include "ast_util.h"
 
 namespace pdr {
 
@@ -448,6 +449,7 @@ namespace pdr {
         else if (is_sat == l_false) {
             uses_level = m_solver.assumes_level();
         }
+        m_solver.set_model(0);
         return is_sat;
     }
 
@@ -481,6 +483,7 @@ namespace pdr {
         prop_solver::scoped_level _sl(m_solver, level);
         m_solver.set_core(&core);
         m_solver.set_subset_based_core(true);
+        m_solver.set_model(0);
         lbool res = m_solver.check_assumptions_and_formula(lits, fml);
         if (res == l_false) {
             lits.reset();
@@ -775,6 +778,13 @@ namespace pdr {
         }
         // only initial states are not set by the PDR search.
         SASSERT(m_model.get());
+        if (!m_model.get()) {
+            std::stringstream msg;
+            msg << "no model for node " << state();
+            IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
+            throw default_exception(msg.str());
+        }
+
         datalog::rule const& rl1 = pt().find_rule(*m_model);
         if (is_ini(rl1)) {
             set_rule(&rl1);
@@ -793,15 +803,23 @@ namespace pdr {
             }
         }
         SASSERT(!tags.empty());
-        ini_tags = m.mk_or(tags.size(), tags.c_ptr());
+        ini_tags = ::mk_or(tags);
         ini_state = m.mk_and(ini_tags, pt().initial_state(), state());
         model_ref mdl;
         pt().get_solver().set_model(&mdl);
-        TRACE("pdr", tout << mk_pp(ini_state, m) << "\n";);
-        VERIFY(l_true == pt().get_solver().check_conjunction_as_assumptions(ini_state));
+        TRACE("pdr", tout << ini_state << "\n";);
+        if (l_true != pt().get_solver().check_conjunction_as_assumptions(ini_state)) {
+            std::stringstream msg;
+            msg << "Unsatisfiable initial state: " << ini_state << "\n";
+            display(msg, 2);
+            IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
+            throw default_exception(msg.str());
+        }
+        SASSERT(mdl.get());
         datalog::rule const& rl2 = pt().find_rule(*mdl);
         SASSERT(is_ini(rl2));
         set_rule(&rl2);
+        pt().get_solver().set_model(0);
         return const_cast<datalog::rule*>(m_rule);                        
     }
 
@@ -830,7 +848,7 @@ namespace pdr {
         }
         r0 = get_rule();
         app_ref_vector& inst = pt().get_inst(r0);
-        TRACE("pdr", tout << mk_pp(state(), m) << " instance: " << inst.size() << "\n";);
+        TRACE("pdr", tout << state() << " instance: " << inst.size() << "\n";);
         for (unsigned i = 0; i < inst.size(); ++i) {
             expr* v;
             if (model.find(inst[i].get(), v)) {
@@ -852,7 +870,7 @@ namespace pdr {
         for (unsigned i = 0; i < indent; ++i) out << " ";
         out << m_level << " " << m_pt.head()->get_name() << " " << (m_closed?"closed":"open") << "\n";
         for (unsigned i = 0; i < indent; ++i) out << " ";
-        out << "  " << mk_pp(m_state, m_state.get_manager(), indent) << "\n";
+        out << "  " << mk_pp(m_state, m_state.get_manager(), indent) << " " << m_state->get_id() << "\n";
         for (unsigned i = 0; i < children().size(); ++i) {
             children()[i]->display(out, indent + 1);
         }
@@ -925,17 +943,6 @@ namespace pdr {
         }
     }
 
-    bool model_search::is_repeated(model_node& n) const {
-        model_node* p = n.parent();
-        while (p) {
-            if (p->state() == n.state()) {
-                TRACE("pdr", tout << n.state() << "repeated\n";);
-                return true;
-            }
-            p = p->parent();
-        }
-        return false;
-    }
 
     void model_search::add_leaf(model_node& n) {
         SASSERT(n.children().empty());
@@ -1012,11 +1019,11 @@ namespace pdr {
         nodes.erase(&n);
         bool is_goal = n.is_goal();
         remove_goal(n);
-        if (!nodes.empty() && is_goal && backtrack) {
+        // TBD: siblings would also fail if n is not a goal.
+        if (!nodes.empty() && backtrack && nodes[0]->children().empty() && nodes[0]->is_closed()) {
             TRACE("pdr_verbose", for (unsigned i = 0; i < nodes.size(); ++i) n.display(tout << &n << "\n", 2););
             model_node* n1 = nodes[0];
-            n1->set_open();
-            SASSERT(n1->children().empty());
+            n1->set_open();            
             enqueue_leaf(n1);
         }
 
@@ -1702,7 +1709,15 @@ namespace pdr {
 
     void context::validate_search() {
         expr_ref tr = m_search.get_trace(*this);
-        // TBD: tr << "\n";
+        smt::kernel solver(m, get_fparams());
+        solver.assert_expr(tr);
+        lbool res = solver.check();
+        if (res != l_true) {
+            std::stringstream msg;
+            msg << "rule validation failed when checking: " << tr;
+            IF_VERBOSE(0, verbose_stream() << msg.str() << "\n";);
+            throw default_exception(msg.str());
+        }                                
     }
 
     void context::validate_model() {
@@ -1938,11 +1953,11 @@ namespace pdr {
         proof_ref proof(m);
         SASSERT(m_last_result == l_true);
         proof = m_search.get_proof_trace(*this);
-        TRACE("pdr", tout << "PDR trace: " << mk_pp(proof, m) << "\n";);
+        TRACE("pdr", tout << "PDR trace: " << proof << "\n";);
         apply(m, m_pc.get(), proof);
-        TRACE("pdr", tout << "PDR trace: " << mk_pp(proof, m) << "\n";);
+        TRACE("pdr", tout << "PDR trace: " << proof << "\n";);
         // proof_utils::push_instantiations_up(proof);
-        // TRACE("pdr", tout << "PDR up: " << mk_pp(proof, m) << "\n";);
+        // TRACE("pdr", tout << "PDR up: " << proof << "\n";);
         return proof;
     }
 
diff --git a/src/muz/pdr/pdr_context.h b/src/muz/pdr/pdr_context.h
index 35b9067b2..ad4b44d90 100644
--- a/src/muz/pdr/pdr_context.h
+++ b/src/muz/pdr/pdr_context.h
@@ -268,7 +268,6 @@ namespace pdr {
         void enqueue_leaf(model_node* n); // add leaf to priority queue.
         void update_models();
         void set_leaf(model_node& n); // Set node as leaf, remove children.
-        bool is_repeated(model_node& n) const;
         unsigned num_goals() const; 
 
     public:

From 6e1c246454930377bb14f249e3827db29878050b Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Mon, 16 Nov 2015 23:06:04 -0800
Subject: [PATCH 05/14] avoid exception in Ratul's environment

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 scripts/mk_util.py | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/scripts/mk_util.py b/scripts/mk_util.py
index 0b924c21f..407c78e13 100644
--- a/scripts/mk_util.py
+++ b/scripts/mk_util.py
@@ -2653,6 +2653,8 @@ def mk_z3consts_py(api_files):
                         z3consts.write('%s = %s\n' % (k, i))
                     z3consts.write('\n')
                     mode = SEARCHING
+                elif len(words) <= 2:
+                    pass
                 else:
                     if words[2] != '':
                         if len(words[2]) > 1 and words[2][1] == 'x':

From 70069e0ae1042ade02fa0a69b3400fc905d58b67 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Tue, 17 Nov 2015 13:50:11 +0000
Subject: [PATCH 06/14] Fixed regular expressions in to expect cross-platform
 newlines.

Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
---
 scripts/mk_util.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/scripts/mk_util.py b/scripts/mk_util.py
index 407c78e13..67b60cbaf 100644
--- a/scripts/mk_util.py
+++ b/scripts/mk_util.py
@@ -2592,7 +2592,7 @@ def mk_z3consts_py(api_files):
     if Z3PY_SRC_DIR is None:
         raise MKException("You must invoke set_z3py_dir(path):")
 
-    blank_pat      = re.compile("^ *$")
+    blank_pat      = re.compile("^ *\r?$")
     comment_pat    = re.compile("^ *//.*$")
     typedef_pat    = re.compile("typedef enum *")
     typedef2_pat   = re.compile("typedef enum { *")
@@ -2654,7 +2654,7 @@ def mk_z3consts_py(api_files):
                     z3consts.write('\n')
                     mode = SEARCHING
                 elif len(words) <= 2:
-                    pass
+                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
                 else:
                     if words[2] != '':
                         if len(words[2]) > 1 and words[2][1] == 'x':
@@ -2672,7 +2672,7 @@ def mk_z3consts_py(api_files):
 
 # Extract enumeration types from z3_api.h, and add .Net definitions
 def mk_z3consts_dotnet(api_files):
-    blank_pat      = re.compile("^ *$")
+    blank_pat      = re.compile("^ *\r?$")
     comment_pat    = re.compile("^ *//.*$")
     typedef_pat    = re.compile("typedef enum *")
     typedef2_pat   = re.compile("typedef enum { *")
@@ -2742,6 +2742,8 @@ def mk_z3consts_dotnet(api_files):
                             z3consts.write('  %s = %s,\n' % (k, i))
                         z3consts.write('  }\n\n')
                     mode = SEARCHING
+                elif len(words) <= 2:
+                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
                 else:
                     if words[2] != '':
                         if len(words[2]) > 1 and words[2][1] == 'x':

From fc05eb65bd7195e5baef7af0b3645c63e3dbd997 Mon Sep 17 00:00:00 2001
From: "Christoph M. Wintersteiger" <cwinter@microsoft.com>
Date: Tue, 17 Nov 2015 13:50:11 +0000
Subject: [PATCH 07/14] Fixed regular expressions in build scripts to expect
 cross-platform newlines.

---
 scripts/mk_util.py | 8 +++++---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/scripts/mk_util.py b/scripts/mk_util.py
index 407c78e13..67b60cbaf 100644
--- a/scripts/mk_util.py
+++ b/scripts/mk_util.py
@@ -2592,7 +2592,7 @@ def mk_z3consts_py(api_files):
     if Z3PY_SRC_DIR is None:
         raise MKException("You must invoke set_z3py_dir(path):")
 
-    blank_pat      = re.compile("^ *$")
+    blank_pat      = re.compile("^ *\r?$")
     comment_pat    = re.compile("^ *//.*$")
     typedef_pat    = re.compile("typedef enum *")
     typedef2_pat   = re.compile("typedef enum { *")
@@ -2654,7 +2654,7 @@ def mk_z3consts_py(api_files):
                     z3consts.write('\n')
                     mode = SEARCHING
                 elif len(words) <= 2:
-                    pass
+                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
                 else:
                     if words[2] != '':
                         if len(words[2]) > 1 and words[2][1] == 'x':
@@ -2672,7 +2672,7 @@ def mk_z3consts_py(api_files):
 
 # Extract enumeration types from z3_api.h, and add .Net definitions
 def mk_z3consts_dotnet(api_files):
-    blank_pat      = re.compile("^ *$")
+    blank_pat      = re.compile("^ *\r?$")
     comment_pat    = re.compile("^ *//.*$")
     typedef_pat    = re.compile("typedef enum *")
     typedef2_pat   = re.compile("typedef enum { *")
@@ -2742,6 +2742,8 @@ def mk_z3consts_dotnet(api_files):
                             z3consts.write('  %s = %s,\n' % (k, i))
                         z3consts.write('  }\n\n')
                     mode = SEARCHING
+                elif len(words) <= 2:
+                    assert False, "Invalid %s, line: %s" % (api_file, linenum)
                 else:
                     if words[2] != '':
                         if len(words[2]) > 1 and words[2][1] == 'x':

From 66fc873613a80c5f2935fbeb29ced4ae8ec2b405 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Tue, 17 Nov 2015 09:00:16 -0800
Subject: [PATCH 08/14] Fix for #322: PDR engine cannot falls back on fixed
 size arithmetic for difference logic. It would eventually overflow and cause
 incorrect model construction. Enable only fixed-size arithmetic when
 configuration allows it

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

diff --git a/src/smt/smt_setup.cpp b/src/smt/smt_setup.cpp
index 524dbeab6..edb4f1e55 100644
--- a/src/smt/smt_setup.cpp
+++ b/src/smt/smt_setup.cpp
@@ -721,8 +721,8 @@ namespace smt {
         IF_VERBOSE(100, verbose_stream() << "(smt.collecting-features)\n";);
         st.collect(m_context.get_num_asserted_formulas(), m_context.get_asserted_formulas());
         IF_VERBOSE(1000, st.display_primitive(verbose_stream()););
-        bool fixnum = st.arith_k_sum_is_small();
-        bool int_only = !st.m_has_rational && !st.m_has_real;
+        bool fixnum = st.arith_k_sum_is_small() && m_params.m_arith_fixnum;
+        bool int_only = !st.m_has_rational && !st.m_has_real && m_params.m_arith_int_only;
         switch(m_params.m_arith_mode) {
         case AS_NO_ARITH:
             m_context.register_plugin(alloc(smt::theory_dummy, m_manager.mk_family_id("arith"), "no arithmetic"));

From d6d301c5ebe10c584798ddfd5f54128d4d83526f Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Tue, 17 Nov 2015 18:38:37 -0800
Subject: [PATCH 09/14] fix for mising handling of quantifiers in tactic. Bug
 #324

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/tactic/arith/eq2bv_tactic.cpp | 14 ++++++++------
 1 file changed, 8 insertions(+), 6 deletions(-)

diff --git a/src/tactic/arith/eq2bv_tactic.cpp b/src/tactic/arith/eq2bv_tactic.cpp
index b84d5567c..7cba66a5a 100644
--- a/src/tactic/arith/eq2bv_tactic.cpp
+++ b/src/tactic/arith/eq2bv_tactic.cpp
@@ -305,14 +305,16 @@ public:
             m_nonfd.mark(f, true);
             expr* e1, *e2;
             if (m.is_eq(f, e1, e2)) {
-                if (is_fd(e1, e2)) {
+				if (is_fd(e1, e2) || is_fd(e2, e1)) {
                     continue;
-                }
-                if (is_fd(e2, e1)) {
-                    continue;
-                }
+                }            
             }
-            m_todo.append(to_app(f)->get_num_args(), to_app(f)->get_args());
+			if (is_app(f)) {
+				m_todo.append(to_app(f)->get_num_args(), to_app(f)->get_args());
+			}
+			else if (is_quantifier(f)) {
+				m_todo.push_back(to_quantifier(f)->get_expr());
+			}
         }
     }
 

From 04b0e3c2f74c318d52de5fa7fb3324d95b89bf56 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Tue, 17 Nov 2015 18:48:52 -0800
Subject: [PATCH 10/14] add checks for cancellation inside mam to agilely not
 ignore Rustan's soft requests for a timeout #326

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

diff --git a/src/smt/mam.cpp b/src/smt/mam.cpp
index d92eef5b8..d22ca88db 100644
--- a/src/smt/mam.cpp
+++ b/src/smt/mam.cpp
@@ -3646,6 +3646,9 @@ namespace smt {
                 approx_set::iterator it1  = plbls1.begin();
                 approx_set::iterator end1 = plbls1.end();
                 for (; it1 != end1; ++it1) {
+                    if (m_context.get_cancel_flag()) {
+                        break;
+                    }
                     unsigned plbl1 = *it1;
                     SASSERT(plbls1.may_contain(plbl1));
                     approx_set::iterator it2  = plbls2.begin();
@@ -3687,6 +3690,9 @@ namespace smt {
                 approx_set::iterator it1  = plbls.begin();
                 approx_set::iterator end1 = plbls.end();
                 for (; it1 != end1; ++it1) {
+                    if (m_context.get_cancel_flag()) {
+                        break;
+                    }
                     unsigned plbl1 = *it1;
                     SASSERT(plbls.may_contain(plbl1));
                     approx_set::iterator it2  = clbls.begin();
@@ -3706,6 +3712,9 @@ namespace smt {
             svector<qp_pair>::iterator it1  = m_new_patterns.begin();
             svector<qp_pair>::iterator end1 = m_new_patterns.end();
             for (; it1 != end1; ++it1) {
+                if (m_context.get_cancel_flag()) {
+                    break;
+                }
                 quantifier * qa    = it1->first;
                 app *        mp    = it1->second;
                 SASSERT(m_ast_manager.is_pattern(mp));

From d7c3e77b66414d1d10f1df73b6b1a792496710e6 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Tue, 17 Nov 2015 18:59:43 -0800
Subject: [PATCH 11/14] port test_capi.c to use mostly essentially
 non-deprecated APIs

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 examples/c/test_capi.c | 489 ++++++++++++++++++++++++-----------------
 1 file changed, 291 insertions(+), 198 deletions(-)

diff --git a/examples/c/test_capi.c b/examples/c/test_capi.c
index 11306a98b..385035361 100644
--- a/examples/c/test_capi.c
+++ b/examples/c/test_capi.c
@@ -83,6 +83,18 @@ Z3_context mk_context_custom(Z3_config cfg, Z3_error_handler err)
     return ctx;
 }
 
+Z3_solver mk_solver(Z3_context ctx) 
+{
+  Z3_solver s = Z3_mk_solver(ctx);
+  Z3_solver_inc_ref(ctx, s);
+  return s;
+}
+
+void del_solver(Z3_context ctx, Z3_solver s)
+{
+  Z3_solver_dec_ref(ctx, s);
+}
+
 /**
    \brief Create a logical context.
 
@@ -184,28 +196,30 @@ Z3_ast mk_binary_app(Z3_context ctx, Z3_func_decl f, Z3_ast x, Z3_ast y)
    \brief Check whether the logical context is satisfiable, and compare the result with the expected result.
    If the context is satisfiable, then display the model.
 */
-void check(Z3_context ctx, Z3_lbool expected_result)
+void check(Z3_context ctx, Z3_solver s, Z3_lbool expected_result)
 {
     Z3_model m      = 0;
-    Z3_lbool result = Z3_check_and_get_model(ctx, &m);
+    Z3_lbool result = Z3_solver_check(ctx, s);
     switch (result) {
     case Z3_L_FALSE:
         printf("unsat\n");
         break;
     case Z3_L_UNDEF:
-        printf("unknown\n");
+        printf("unknown\n");        
+	m = Z3_solver_get_model(ctx, s);
+	if (m) Z3_model_inc_ref(ctx, m);
         printf("potential model:\n%s\n", Z3_model_to_string(ctx, m));
         break;
     case Z3_L_TRUE:
+	m = Z3_solver_get_model(ctx, s);
+	if (m) Z3_model_inc_ref(ctx, m);
         printf("sat\n%s\n", Z3_model_to_string(ctx, m));
         break;
     }
-    if (m) {
-        Z3_del_model(ctx, m);
-    }
     if (result != expected_result) {
         exitf("unexpected result");
     }
+    if (m) Z3_model_dec_ref(ctx, m);
 }
 
 /**
@@ -218,20 +232,18 @@ void check(Z3_context ctx, Z3_lbool expected_result)
 
    The context \c ctx is not modified by this function.
 */
-void prove(Z3_context ctx, Z3_ast f, Z3_bool is_valid)
+void prove(Z3_context ctx, Z3_solver s, Z3_ast f, Z3_bool is_valid)
 {
-    Z3_model m;
+    Z3_model m = 0;
     Z3_ast   not_f;
 
     /* save the current state of the context */
-    Z3_push(ctx);
+    Z3_solver_push(ctx, s);
 
     not_f = Z3_mk_not(ctx, f);
-    Z3_assert_cnstr(ctx, not_f);
-    
-    m = 0;
-    
-    switch (Z3_check_and_get_model(ctx, &m)) {
+    Z3_solver_assert(ctx, s, not_f);
+        
+    switch (Z3_solver_check(ctx, s)) {
     case Z3_L_FALSE:
         /* proved */
         printf("valid\n");
@@ -242,9 +254,11 @@ void prove(Z3_context ctx, Z3_ast f, Z3_bool is_valid)
     case Z3_L_UNDEF:
         /* Z3 failed to prove/disprove f. */
         printf("unknown\n");
+        m = Z3_solver_get_model(ctx, s);
         if (m != 0) {
+	  Z3_model_inc_ref(ctx, m);
             /* m should be viewed as a potential counterexample. */
-            printf("potential counterexample:\n%s\n", Z3_model_to_string(ctx, m));
+  	    printf("potential counterexample:\n%s\n", Z3_model_to_string(ctx, m));
         }
         if (is_valid) {
             exitf("unexpected result");
@@ -253,7 +267,9 @@ void prove(Z3_context ctx, Z3_ast f, Z3_bool is_valid)
     case Z3_L_TRUE:
         /* disproved */
         printf("invalid\n");
+        m = Z3_solver_get_model(ctx, s);
         if (m) {
+	  Z3_model_inc_ref(ctx, m);
             /* the model returned by Z3 is a counterexample */
             printf("counterexample:\n%s\n", Z3_model_to_string(ctx, m));
         }
@@ -262,13 +278,10 @@ void prove(Z3_context ctx, Z3_ast f, Z3_bool is_valid)
         }
         break;
     }
+    if (m) Z3_model_dec_ref(ctx, m);
 
-    if (m) {
-        Z3_del_model(ctx, m);
-    }
-
-    /* restore context */
-    Z3_pop(ctx, 1);
+    /* restore scope */
+    Z3_solver_pop(ctx, s, 1);
 }
 
 /**
@@ -281,7 +294,7 @@ void prove(Z3_context ctx, Z3_ast f, Z3_bool is_valid)
 
    Where, \c finv is a fresh function declaration.
 */
-void assert_inj_axiom(Z3_context ctx, Z3_func_decl f, unsigned i) 
+void assert_inj_axiom(Z3_context ctx, Z3_solver s, Z3_func_decl f, unsigned i) 
 {
     unsigned sz, j;
     Z3_sort finv_domain, finv_range;
@@ -339,7 +352,7 @@ void assert_inj_axiom(Z3_context ctx, Z3_func_decl f, unsigned i)
                                  names,
                                  eq);
     printf("assert axiom:\n%s\n", Z3_ast_to_string(ctx, q));
-    Z3_assert_cnstr(ctx, q);
+    Z3_solver_assert(ctx, s, q);
 
     /* free temporary arrays */
     free(types);
@@ -352,7 +365,7 @@ void assert_inj_axiom(Z3_context ctx, Z3_func_decl f, unsigned i)
    
    This example uses the SMT-LIB parser to simplify the axiom construction.
 */
-void assert_comm_axiom(Z3_context ctx, Z3_func_decl f) 
+void assert_comm_axiom(Z3_context ctx, Z3_solver s, Z3_func_decl f) 
 {
     Z3_sort t;
     Z3_symbol f_name, t_name;
@@ -379,7 +392,7 @@ void assert_comm_axiom(Z3_context ctx, Z3_func_decl f)
                            1, &f_name, &f);
     q = Z3_get_smtlib_formula(ctx, 0);
     printf("assert axiom:\n%s\n", Z3_ast_to_string(ctx, q));
-    Z3_assert_cnstr(ctx, q);
+    Z3_solver_assert(ctx, s, q);
 }
 
 /**
@@ -554,42 +567,50 @@ void display_function_interpretations(Z3_context c, FILE * out, Z3_model m)
 
     fprintf(out, "function interpretations:\n");
 
-    num_functions = Z3_get_model_num_funcs(c, m);
+    num_functions = Z3_model_get_num_funcs(c, m);
     for (i = 0; i < num_functions; i++) {
         Z3_func_decl fdecl;
         Z3_symbol name;
         Z3_ast func_else;
-        unsigned num_entries, j;
+        unsigned num_entries = 0, j;
+        Z3_func_interp_opt finterp;
         
-        fdecl = Z3_get_model_func_decl(c, m, i);
+        fdecl = Z3_model_get_func_decl(c, m, i);
+        finterp = Z3_model_get_func_interp(c, m, fdecl);
+	Z3_func_interp_inc_ref(c, finterp);
         name = Z3_get_decl_name(c, fdecl);
         display_symbol(c, out, name);
         fprintf(out, " = {");
-        num_entries = Z3_get_model_func_num_entries(c, m, i);
+        if (finterp) 
+          num_entries = Z3_func_interp_get_num_entries(c, finterp);
         for (j = 0; j < num_entries; j++) {
             unsigned num_args, k;
+            Z3_func_entry fentry = Z3_func_interp_get_entry(c, finterp, j);
+	    Z3_func_entry_inc_ref(c, fentry);
             if (j > 0) {
                 fprintf(out, ", ");
             }
-            num_args = Z3_get_model_func_entry_num_args(c, m, i, j);
+            num_args = Z3_func_entry_get_num_args(c, fentry);
             fprintf(out, "(");
             for (k = 0; k < num_args; k++) {
                 if (k > 0) {
                     fprintf(out, ", ");
                 }
-                display_ast(c, out, Z3_get_model_func_entry_arg(c, m, i, j, k));
+                display_ast(c, out, Z3_func_entry_get_arg(c, fentry, k));
             }
             fprintf(out, "|->");
-            display_ast(c, out, Z3_get_model_func_entry_value(c, m, i, j));
+            display_ast(c, out, Z3_func_entry_get_value(c, fentry));
             fprintf(out, ")");
+	    Z3_func_entry_dec_ref(c, fentry);
         }
         if (num_entries > 0) {
             fprintf(out, ", ");
         }
         fprintf(out, "(else|->");
-        func_else = Z3_get_model_func_else(c, m, i);
+        func_else = Z3_func_interp_get_else(c, finterp);
         display_ast(c, out, func_else);
         fprintf(out, ")}\n");
+	Z3_func_interp_dec_ref(c, finterp);
     }
 }
 
@@ -601,10 +622,12 @@ void display_model(Z3_context c, FILE * out, Z3_model m)
     unsigned num_constants;
     unsigned i;
 
-    num_constants = Z3_get_model_num_constants(c, m);
+    if (!m) return;
+
+    num_constants = Z3_model_get_num_consts(c, m);
     for (i = 0; i < num_constants; i++) {
         Z3_symbol name;
-        Z3_func_decl cnst = Z3_get_model_constant(c, m, i);
+        Z3_func_decl cnst = Z3_model_get_const_decl(c, m, i);
         Z3_ast a, v;
         Z3_bool ok;
         name = Z3_get_decl_name(c, cnst);
@@ -612,7 +635,7 @@ void display_model(Z3_context c, FILE * out, Z3_model m)
         fprintf(out, " = ");
         a = Z3_mk_app(c, cnst, 0, 0);
         v = a;
-        ok = Z3_eval(c, m, a, &v);
+        ok = Z3_model_eval(c, m, a, 1, &v);
         display_ast(c, out, v);
         fprintf(out, "\n");
     }
@@ -622,10 +645,10 @@ void display_model(Z3_context c, FILE * out, Z3_model m)
 /**
    \brief Similar to #check, but uses #display_model instead of #Z3_model_to_string.
 */
-void check2(Z3_context ctx, Z3_lbool expected_result)
+void check2(Z3_context ctx, Z3_solver s, Z3_lbool expected_result)
 {
     Z3_model m      = 0;
-    Z3_lbool result = Z3_check_and_get_model(ctx, &m);
+    Z3_lbool result = Z3_solver_check(ctx, s);
     switch (result) {
     case Z3_L_FALSE:
         printf("unsat\n");
@@ -633,19 +656,22 @@ void check2(Z3_context ctx, Z3_lbool expected_result)
     case Z3_L_UNDEF:
         printf("unknown\n");
         printf("potential model:\n");
+        m = Z3_solver_get_model(ctx, s);
+	if (m) Z3_model_inc_ref(ctx, m);
         display_model(ctx, stdout, m);
         break;
     case Z3_L_TRUE:
         printf("sat\n");
+        m = Z3_solver_get_model(ctx, s);
+	if (m) Z3_model_inc_ref(ctx, m);
         display_model(ctx, stdout, m);
         break;
     }
-    if (m) {
-        Z3_del_model(ctx, m);
-    }
     if (result != expected_result) {
         exitf("unexpected result");
     }
+    if (m) Z3_model_dec_ref(ctx, m);
+
 }
 
 /**
@@ -674,9 +700,6 @@ void simple_example()
  
     ctx = mk_context();
 
-    /* do something with the context */
-    printf("CONTEXT:\n%sEND OF CONTEXT\n", Z3_context_to_string(ctx));
-
     /* delete logical context */
     Z3_del_context(ctx);
 }
@@ -689,6 +712,7 @@ void demorgan()
 {
     Z3_config cfg;
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort bool_sort;
     Z3_symbol symbol_x, symbol_y;
     Z3_ast x, y, not_x, not_y, x_and_y, ls, rs, conjecture, negated_conjecture;
@@ -719,9 +743,10 @@ void demorgan()
     rs                 = Z3_mk_or(ctx, 2, args);
     conjecture         = Z3_mk_iff(ctx, ls, rs);
     negated_conjecture = Z3_mk_not(ctx, conjecture);
-    
-    Z3_assert_cnstr(ctx, negated_conjecture);
-    switch (Z3_check(ctx)) {
+   
+    s = mk_solver(ctx); 
+    Z3_solver_assert(ctx, s, negated_conjecture);
+    switch (Z3_solver_check(ctx, s)) {
     case Z3_L_FALSE:
         /* The negated conjecture was unsatisfiable, hence the conjecture is valid */
         printf("DeMorgan is valid\n");
@@ -735,6 +760,7 @@ void demorgan()
         printf("DeMorgan is not valid\n");
         break;
     }
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -745,21 +771,24 @@ void find_model_example1()
 {
     Z3_context ctx;
     Z3_ast x, y, x_xor_y;
+    Z3_solver s;
 
     printf("\nfind_model_example1\n");
     LOG_MSG("find_model_example1");
 
     ctx     = mk_context();
+    s       = mk_solver(ctx);
 
     x       = mk_bool_var(ctx, "x");
     y       = mk_bool_var(ctx, "y");
     x_xor_y = Z3_mk_xor(ctx, x, y);
     
-    Z3_assert_cnstr(ctx, x_xor_y);
+    Z3_solver_assert(ctx, s, x_xor_y);
 
     printf("model for: x xor y\n");
-    check(ctx, Z3_L_TRUE);
+    check(ctx, s, Z3_L_TRUE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -774,11 +803,13 @@ void find_model_example2()
     Z3_ast x_eq_y;
     Z3_ast args[2];
     Z3_ast c1, c2, c3;
+    Z3_solver s;
 
     printf("\nfind_model_example2\n");
     LOG_MSG("find_model_example2");
     
     ctx        = mk_context();
+    s          = mk_solver(ctx);
     x          = mk_int_var(ctx, "x");
     y          = mk_int_var(ctx, "y");
     one        = mk_int(ctx, 1);
@@ -791,20 +822,21 @@ void find_model_example2()
     c1         = Z3_mk_lt(ctx, x, y_plus_one);
     c2         = Z3_mk_gt(ctx, x, two);
     
-    Z3_assert_cnstr(ctx, c1);
-    Z3_assert_cnstr(ctx, c2);
+    Z3_solver_assert(ctx, s, c1);
+    Z3_solver_assert(ctx, s, c2);
 
     printf("model for: x < y + 1, x > 2\n");
-    check(ctx, Z3_L_TRUE);
+    check(ctx, s, Z3_L_TRUE);
 
     /* assert not(x = y) */
     x_eq_y     = Z3_mk_eq(ctx, x, y);
     c3         = Z3_mk_not(ctx, x_eq_y);
-    Z3_assert_cnstr(ctx, c3);
+    Z3_solver_assert(ctx, s,c3);
 
     printf("model for: x < y + 1, x > 2, not(x = y)\n");
-    check(ctx, Z3_L_TRUE);
+    check(ctx, s, Z3_L_TRUE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -818,6 +850,7 @@ void find_model_example2()
 void prove_example1() 
 {
     Z3_context ctx;
+    Z3_solver s;
     Z3_symbol U_name, g_name, x_name, y_name;
     Z3_sort U;
     Z3_sort g_domain[1];
@@ -829,7 +862,8 @@ void prove_example1()
     LOG_MSG("prove_example1");
     
     ctx        = mk_context();
-    
+    s          = mk_solver(ctx);
+
     /* create uninterpreted type. */
     U_name     = Z3_mk_string_symbol(ctx, "U");
     U          = Z3_mk_uninterpreted_sort(ctx, U_name);
@@ -850,12 +884,12 @@ void prove_example1()
     
     /* assert x = y */
     eq          = Z3_mk_eq(ctx, x, y);
-    Z3_assert_cnstr(ctx, eq);
+    Z3_solver_assert(ctx, s, eq);
 
     /* prove g(x) = g(y) */
     f           = Z3_mk_eq(ctx, gx, gy);
     printf("prove: x = y implies g(x) = g(y)\n");
-    prove(ctx, f, Z3_TRUE);
+    prove(ctx, s, f, Z3_TRUE);
 
     /* create g(g(x)) */
     ggx         = mk_unary_app(ctx, g, gx);
@@ -863,8 +897,9 @@ void prove_example1()
     /* disprove g(g(x)) = g(y) */
     f           = Z3_mk_eq(ctx, ggx, gy);
     printf("disprove: x = y implies g(g(x)) = g(y)\n");
-    prove(ctx, f, Z3_FALSE);
+    prove(ctx, s, f, Z3_FALSE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -877,6 +912,7 @@ void prove_example1()
 void prove_example2() 
 {
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort int_sort;
     Z3_symbol g_name;
     Z3_sort g_domain[1];
@@ -889,6 +925,7 @@ void prove_example2()
     LOG_MSG("prove_example2");
     
     ctx        = mk_context();
+    s          = mk_solver(ctx);
 
     /* declare function g */
     int_sort    = Z3_mk_int_sort(ctx);
@@ -916,30 +953,31 @@ void prove_example2()
     ggx_gy      = mk_unary_app(ctx, g, gx_gy);
     eq          = Z3_mk_eq(ctx, ggx_gy, gz);
     c1          = Z3_mk_not(ctx, eq);
-    Z3_assert_cnstr(ctx, c1);
+    Z3_solver_assert(ctx, s, c1);
 
     /* assert x + z <= y */
     args[0]     = x;
     args[1]     = z;
     x_plus_z    = Z3_mk_add(ctx, 2, args);
     c2          = Z3_mk_le(ctx, x_plus_z, y);
-    Z3_assert_cnstr(ctx, c2);
+    Z3_solver_assert(ctx, s, c2);
 
     /* assert y <= x */
     c3          = Z3_mk_le(ctx, y, x);
-    Z3_assert_cnstr(ctx, c3);
+    Z3_solver_assert(ctx, s, c3);
 
     /* prove z < 0 */
     f           = Z3_mk_lt(ctx, z, zero);
     printf("prove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < 0\n");
-    prove(ctx, f, Z3_TRUE);
+    prove(ctx, s, f, Z3_TRUE);
 
     /* disprove z < -1 */
     minus_one   = mk_int(ctx, -1);
     f           = Z3_mk_lt(ctx, z, minus_one);
     printf("disprove: not(g(g(x) - g(y)) = g(z)), x + z <= y <= x implies z < -1\n");
-    prove(ctx, f, Z3_FALSE);
+    prove(ctx, s, f, Z3_FALSE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -952,6 +990,7 @@ void prove_example2()
 void push_pop_example1() 
 {
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort int_sort;
     Z3_symbol x_sym, y_sym;
     Z3_ast x, y, big_number, three;
@@ -961,6 +1000,7 @@ void push_pop_example1()
     LOG_MSG("push_pop_example1");
 
     ctx        = mk_context();
+    s          = mk_solver(ctx);
 
     /* create a big number */
     int_sort   = Z3_mk_int_sort(ctx);
@@ -976,32 +1016,32 @@ void push_pop_example1()
     /* assert x >= "big number" */
     c1         = Z3_mk_ge(ctx, x, big_number);
     printf("assert: x >= 'big number'\n");
-    Z3_assert_cnstr(ctx, c1);
+    Z3_solver_assert(ctx, s, c1);
 
     /* create a backtracking point */
     printf("push\n");
-    Z3_push(ctx);
+    Z3_solver_push(ctx, s);
 
-    printf("number of scopes: %d\n", Z3_get_num_scopes(ctx));
+    printf("number of scopes: %d\n", Z3_solver_get_num_scopes(ctx, s));
 
     /* assert x <= 3 */
     c2         = Z3_mk_le(ctx, x, three);
     printf("assert: x <= 3\n");
-    Z3_assert_cnstr(ctx, c2);
+    Z3_solver_assert(ctx, s, c2);
 
     /* context is inconsistent at this point */
-    check2(ctx, Z3_L_FALSE);
+    check2(ctx, s, Z3_L_FALSE);
 
     /* backtrack: the constraint x <= 3 will be removed, since it was
-       asserted after the last Z3_push. */
+       asserted after the last Z3_solver_push. */
     printf("pop\n");
-    Z3_pop(ctx, 1);
+    Z3_solver_pop(ctx, s, 1);
 
-    printf("number of scopes: %d\n", Z3_get_num_scopes(ctx));
+    printf("number of scopes: %d\n", Z3_solver_get_num_scopes(ctx, s));
 
 
     /* the context is consistent again. */
-    check2(ctx, Z3_L_TRUE);
+    check2(ctx, s, Z3_L_TRUE);
 
     /* new constraints can be asserted... */
     
@@ -1012,11 +1052,12 @@ void push_pop_example1()
     /* assert y > x */
     c3         = Z3_mk_gt(ctx, y, x);
     printf("assert: y > x\n");
-    Z3_assert_cnstr(ctx, c3);
+    Z3_solver_assert(ctx, s, c3);
 
     /* the context is still consistent. */
-    check2(ctx, Z3_L_TRUE);
+    check2(ctx, s, Z3_L_TRUE);
     
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1030,6 +1071,7 @@ void quantifier_example1()
 {
     Z3_config  cfg;
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort       int_sort;
     Z3_symbol         f_name;
     Z3_sort       f_domain[2];
@@ -1052,6 +1094,7 @@ void quantifier_example1()
     Z3_global_param_set("smt.mbqi.max_iterations", "10");
     ctx = mk_context_custom(cfg, error_handler);
     Z3_del_config(cfg);
+    s = mk_solver(ctx);
 
     /* declare function f */
     int_sort    = Z3_mk_int_sort(ctx);
@@ -1061,7 +1104,7 @@ void quantifier_example1()
     f           = Z3_mk_func_decl(ctx, f_name, 2, f_domain, int_sort);
   
     /* assert that f is injective in the second argument. */
-    assert_inj_axiom(ctx, f, 1);
+    assert_inj_axiom(ctx, s, f, 1);
     
     /* create x, y, v, w, fxy, fwv */
     x           = mk_int_var(ctx, "x");
@@ -1073,26 +1116,23 @@ void quantifier_example1()
     
     /* assert f(x, y) = f(w, v) */
     p1          = Z3_mk_eq(ctx, fxy, fwv);
-    Z3_assert_cnstr(ctx, p1);
+    Z3_solver_assert(ctx, s, p1);
 
     /* prove f(x, y) = f(w, v) implies y = v */
     p2          = Z3_mk_eq(ctx, y, v);
     printf("prove: f(x, y) = f(w, v) implies y = v\n");
-    prove(ctx, p2, Z3_TRUE);
+    prove(ctx, s, p2, Z3_TRUE);
 
     /* disprove f(x, y) = f(w, v) implies x = w */
     /* using check2 instead of prove */
     p3          = Z3_mk_eq(ctx, x, w);
     not_p3      = Z3_mk_not(ctx, p3);
-    Z3_assert_cnstr(ctx, not_p3);
+    Z3_solver_assert(ctx, s, not_p3);
     printf("disprove: f(x, y) = f(w, v) implies x = w\n");
     printf("that is: not(f(x, y) = f(w, v) implies x = w) is satisfiable\n");
-    check2(ctx, Z3_L_UNDEF);
-    printf("reason for last failure: %d (7 = quantifiers)\n", 
-           Z3_get_search_failure(ctx));
-    if (Z3_get_search_failure(ctx) != Z3_QUANTIFIERS) {
-        exitf("unexpected result");
-    }
+    check2(ctx, s, Z3_L_UNDEF);
+    printf("reason for last failure: %s\n",  Z3_solver_get_reason_unknown(ctx, s));
+    del_solver(ctx, s);
     Z3_del_context(ctx);
     /* reset global parameters set by this function */
     Z3_global_param_reset_all(); 
@@ -1105,7 +1145,8 @@ void quantifier_example1()
 */
 void array_example1() 
 {
-    Z3_context ctx;
+    Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort int_sort, array_sort;
     Z3_ast a1, a2, i1, v1, i2, v2, i3;
     Z3_ast st1, st2, sel1, sel2;
@@ -1116,7 +1157,6 @@ void array_example1()
     printf("\narray_example1\n");
     LOG_MSG("array_example1");
 
-    ctx = mk_context();
 
     int_sort    = Z3_mk_int_sort(ctx);
     array_sort  = Z3_mk_array_sort(ctx, int_sort, int_sort);
@@ -1148,8 +1188,9 @@ void array_example1()
     thm         = Z3_mk_implies(ctx, antecedent, consequent);
     printf("prove: store(a1, i1, v1) = store(a2, i2, v2) implies (i1 = i3 or i2 = i3 or select(a1, i3) = select(a2, i3))\n");
     printf("%s\n", Z3_ast_to_string(ctx, thm));
-    prove(ctx, thm, Z3_TRUE);
+    prove(ctx, s, thm, Z3_TRUE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1163,6 +1204,7 @@ void array_example1()
 void array_example2() 
 {
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort bool_sort, array_sort;
     Z3_ast      a[5];
     Z3_ast      d;
@@ -1174,6 +1216,7 @@ void array_example2()
     for (n = 2; n <= 5; n++) {
         printf("n = %d\n", n);
         ctx = mk_context();
+        s = mk_solver(ctx);
         
         bool_sort   = Z3_mk_bool_sort(ctx);
         array_sort  = Z3_mk_array_sort(ctx, bool_sort, bool_sort);
@@ -1187,11 +1230,12 @@ void array_example2()
         /* assert distinct(a[0], ..., a[n]) */
         d = Z3_mk_distinct(ctx, n, a);
         printf("%s\n", Z3_ast_to_string(ctx, d));
-        Z3_assert_cnstr(ctx, d);
+        Z3_solver_assert(ctx, s, d);
 
         /* context is satisfiable if n < 5 */
-        check2(ctx, n < 5 ? Z3_L_TRUE : Z3_L_FALSE);
+        check2(ctx, s, n < 5 ? Z3_L_TRUE : Z3_L_FALSE);
         
+	del_solver(ctx, s);
         Z3_del_context(ctx);
     }
 }
@@ -1201,13 +1245,13 @@ void array_example2()
 */
 void array_example3() 
 {
-    Z3_context ctx;
+    Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort bool_sort, int_sort, array_sort;
     Z3_sort domain, range;
     printf("\narray_example3\n");
     LOG_MSG("array_example3");
 
-    ctx      = mk_context();
 
     bool_sort  = Z3_mk_bool_sort(ctx);
     int_sort   = Z3_mk_int_sort(ctx); 
@@ -1231,6 +1275,7 @@ void array_example3()
         exitf("invalid array type");
     }
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1239,7 +1284,8 @@ void array_example3()
 */
 void tuple_example1() 
 {
-    Z3_context         ctx;
+    Z3_context  ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort        real_sort, pair_sort;
     Z3_symbol          mk_tuple_name;
     Z3_func_decl  mk_tuple_decl;
@@ -1251,7 +1297,6 @@ void tuple_example1()
     printf("\ntuple_example1\n");
     LOG_MSG("tuple_example1");
     
-    ctx       = mk_context();
 
     real_sort = Z3_mk_real_sort(ctx);
 
@@ -1284,13 +1329,13 @@ void tuple_example1()
         eq2  = Z3_mk_eq(ctx, x, one);
         thm  = Z3_mk_implies(ctx, eq1, eq2);
         printf("prove: get_x(mk_pair(x, y)) = 1 implies x = 1\n");
-        prove(ctx, thm, Z3_TRUE);
+        prove(ctx, s, thm, Z3_TRUE);
 
         /* disprove that get_x(mk_pair(x,y)) == 1 implies y = 1*/
         eq3  = Z3_mk_eq(ctx, y, one);
         thm  = Z3_mk_implies(ctx, eq1, eq3);
         printf("disprove: get_x(mk_pair(x, y)) = 1 implies y = 1\n");
-        prove(ctx, thm, Z3_FALSE);
+        prove(ctx, s, thm, Z3_FALSE);
     }
 
     {
@@ -1311,12 +1356,12 @@ void tuple_example1()
         consequent     = Z3_mk_eq(ctx, p1, p2);
         thm            = Z3_mk_implies(ctx, antecedent, consequent);
         printf("prove: get_x(p1) = get_x(p2) and get_y(p1) = get_y(p2) implies p1 = p2\n");
-        prove(ctx, thm, Z3_TRUE);
+        prove(ctx, s, thm, Z3_TRUE);
 
         /* disprove that get_x(p1) = get_x(p2) implies p1 = p2 */
         thm            = Z3_mk_implies(ctx, antecedents[0], consequent);
         printf("disprove: get_x(p1) = get_x(p2) implies p1 = p2\n");
-        prove(ctx, thm, Z3_FALSE);
+        prove(ctx, s, thm, Z3_FALSE);
     }
 
     {
@@ -1335,16 +1380,17 @@ void tuple_example1()
         consequent     = Z3_mk_eq(ctx, x, ten);
         thm            = Z3_mk_implies(ctx, antecedent, consequent);
         printf("prove: p2 = update(p1, 0, 10) implies get_x(p2) = 10\n");
-        prove(ctx, thm, Z3_TRUE);
+        prove(ctx, s, thm, Z3_TRUE);
 
         /* disprove that p2 = update(p1, 0, 10) implies get_y(p2) = 10 */
         y              = mk_unary_app(ctx, get_y_decl, p2);
         consequent     = Z3_mk_eq(ctx, y, ten);
         thm            = Z3_mk_implies(ctx, antecedent, consequent);
         printf("disprove: p2 = update(p1, 0, 10) implies get_y(p2) = 10\n");
-        prove(ctx, thm, Z3_FALSE);
+        prove(ctx, s, thm, Z3_FALSE);
     }
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1353,14 +1399,14 @@ void tuple_example1()
 */
 void bitvector_example1() 
 {
-    Z3_context         ctx;
+    Z3_context ctx = mk_context();
+    Z3_solver  s = mk_solver(ctx);
     Z3_sort        bv_sort;
     Z3_ast             x, zero, ten, x_minus_ten, c1, c2, thm;
 
     printf("\nbitvector_example1\n");
     LOG_MSG("bitvector_example1");
     
-    ctx       = mk_context();
     
     bv_sort   = Z3_mk_bv_sort(ctx, 32);
     
@@ -1373,8 +1419,9 @@ void bitvector_example1()
     c2          = Z3_mk_bvsle(ctx, x_minus_ten, zero);
     thm         = Z3_mk_iff(ctx, c1, c2);
     printf("disprove: x - 10 <= 0 IFF x <= 10 for (32-bit) machine integers\n");
-    prove(ctx, thm, Z3_FALSE);
+    prove(ctx, s, thm, Z3_FALSE);
     
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1384,6 +1431,7 @@ void bitvector_example1()
 void bitvector_example2()
 {
     Z3_context ctx = mk_context();
+    Z3_solver  s = mk_solver(ctx);
  
     /* construct x ^ y - 103 == x * y */
     Z3_sort bv_sort = Z3_mk_bv_sort(ctx, 32);
@@ -1400,11 +1448,12 @@ void bitvector_example2()
     printf("find values of x and y, such that x ^ y - 103 == x * y\n");
     
     /* add the constraint <tt>x ^ y - 103 == x * y<\tt> to the logical context */
-    Z3_assert_cnstr(ctx, ctr);
+    Z3_solver_assert(ctx, s, ctr);
     
     /* find a model (i.e., values for x an y that satisfy the constraint */
-    check(ctx, Z3_L_TRUE);
+    check(ctx, s, Z3_L_TRUE);
     
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1413,36 +1462,38 @@ void bitvector_example2()
 */
 void eval_example1() 
 {
-    Z3_context ctx;
+    Z3_context ctx = mk_context();
+    Z3_solver  s = mk_solver(ctx);
     Z3_ast x, y, two;
     Z3_ast c1, c2;
-    Z3_model m;
+    Z3_model m = 0;
 
     printf("\neval_example1\n");
     LOG_MSG("eval_example1");
     
-    ctx        = mk_context();
     x          = mk_int_var(ctx, "x");
     y          = mk_int_var(ctx, "y");
     two        = mk_int(ctx, 2);
     
     /* assert x < y */
     c1         = Z3_mk_lt(ctx, x, y);
-    Z3_assert_cnstr(ctx, c1);
+    Z3_solver_assert(ctx, s, c1);
 
     /* assert x > 2 */
     c2         = Z3_mk_gt(ctx, x, two);
-    Z3_assert_cnstr(ctx, c2);
+    Z3_solver_assert(ctx, s, c2);
 
     /* find model for the constraints above */
-    if (Z3_check_and_get_model(ctx, &m) == Z3_L_TRUE) {
+    if (Z3_solver_check(ctx, s) == Z3_L_TRUE) {
         Z3_ast   x_plus_y;
         Z3_ast   args[2] = {x, y};
         Z3_ast v;
+        m = Z3_solver_get_model(ctx, s);
+	if (m) Z3_model_inc_ref(ctx, m);
         printf("MODEL:\n%s", Z3_model_to_string(ctx, m));
         x_plus_y = Z3_mk_add(ctx, 2, args);
         printf("\nevaluating x+y\n");
-        if (Z3_eval(ctx, m, x_plus_y, &v)) {
+        if (Z3_model_eval(ctx, m, x_plus_y, 1, &v)) {
             printf("result = ");
             display_ast(ctx, stdout, v);
             printf("\n");
@@ -1450,12 +1501,13 @@ void eval_example1()
         else {
             exitf("failed to evaluate: x+y");
         }
-        Z3_del_model(ctx, m);
     }
     else {
         exitf("the constraints are satisfiable");
     }
 
+    if (m) Z3_model_dec_ref(ctx, m);
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1492,6 +1544,7 @@ void error_code_example1()
 {
     Z3_config cfg;
     Z3_context ctx;
+    Z3_solver s;
     Z3_ast x;
     Z3_model m;
     Z3_ast v;
@@ -1505,16 +1558,19 @@ void error_code_example1()
     cfg = Z3_mk_config();
     ctx = mk_context_custom(cfg, NULL);
     Z3_del_config(cfg);
+    s = mk_solver(ctx);
 
     x          = mk_bool_var(ctx, "x");
     x_decl     = Z3_get_app_decl(ctx, Z3_to_app(ctx, x));
-    Z3_assert_cnstr(ctx, x);
+    Z3_solver_assert(ctx, s, x);
     
-    if (Z3_check_and_get_model(ctx, &m) != Z3_L_TRUE) {
+    if (Z3_solver_check(ctx, s) != Z3_L_TRUE) {
         exitf("unexpected result");
     }
 
-    if (!Z3_eval_func_decl(ctx, m, x_decl, &v)) {
+    m = Z3_solver_get_model(ctx, s);
+    if (m) Z3_model_inc_ref(ctx, m);
+    if (!Z3_model_eval(ctx, m, x, 1, &v)) {
         exitf("did not obtain value for declaration.\n");
     }
     if (Z3_get_error_code(ctx) == Z3_OK) {
@@ -1525,7 +1581,8 @@ void error_code_example1()
     if (Z3_get_error_code(ctx) != Z3_OK) {
         printf("last call failed.\n");
     }
-    Z3_del_model(ctx, m);
+    if (m) Z3_model_dec_ref(ctx, m);
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1558,7 +1615,7 @@ void error_code_example2() {
         Z3_del_context(ctx);
     }
     else {
-        printf("Z3 error: %s.\n", Z3_get_error_msg((Z3_error_code)r));
+      printf("Z3 error: %s.\n", Z3_get_error_msg_ex(ctx, (Z3_error_code)r));
         if (ctx != NULL) {
             Z3_del_context(ctx);
         }
@@ -1570,13 +1627,13 @@ void error_code_example2() {
  */
 void parser_example1() 
 {
-    Z3_context ctx;
+    Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     unsigned i, num_formulas;
 
     printf("\nparser_example1\n");
     LOG_MSG("parser_example1");
     
-    ctx        = mk_context();
    
     Z3_parse_smtlib_string(ctx, 
                            "(benchmark tst :extrafuns ((x Int) (y Int)) :formula (> x y) :formula (> x 0))",
@@ -1586,11 +1643,12 @@ void parser_example1()
     for (i = 0; i < num_formulas; i++) {
         Z3_ast f = Z3_get_smtlib_formula(ctx, i);
         printf("formula %d: %s\n", i, Z3_ast_to_string(ctx, f));
-        Z3_assert_cnstr(ctx, f);
+        Z3_solver_assert(ctx, s, f);
     }
     
-    check(ctx, Z3_L_TRUE);
+    check(ctx, s, Z3_L_TRUE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1599,7 +1657,8 @@ void parser_example1()
  */
 void parser_example2() 
 {
-    Z3_context ctx;
+    Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_ast x, y;
     Z3_symbol         names[2];
     Z3_func_decl decls[2];
@@ -1608,7 +1667,6 @@ void parser_example2()
     printf("\nparser_example2\n");
     LOG_MSG("parser_example2");
 
-    ctx        = mk_context();
 
     /* Z3_enable_arithmetic doesn't need to be invoked in this example
        because it will be implicitly invoked by mk_int_var.
@@ -1629,9 +1687,10 @@ void parser_example2()
                            2, names, decls);
     f = Z3_get_smtlib_formula(ctx, 0);
     printf("formula: %s\n", Z3_ast_to_string(ctx, f));
-    Z3_assert_cnstr(ctx, f);
-    check(ctx, Z3_L_TRUE);
+    Z3_solver_assert(ctx, s, f);
+    check(ctx, s, Z3_L_TRUE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1642,6 +1701,7 @@ void parser_example3()
 {
     Z3_config  cfg;
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort       int_sort;
     Z3_symbol     g_name;
     Z3_sort       g_domain[2];
@@ -1656,6 +1716,7 @@ void parser_example3()
     Z3_set_param_value(cfg, "model", "true");
     ctx = mk_context_custom(cfg, error_handler);
     Z3_del_config(cfg);
+    s = mk_solver(ctx);
 
     /* declare function g */
     int_sort    = Z3_mk_int_sort(ctx);
@@ -1664,7 +1725,7 @@ void parser_example3()
     g_domain[1] = int_sort;
     g           = Z3_mk_func_decl(ctx, g_name, 2, g_domain, int_sort);
     
-    assert_comm_axiom(ctx, g);
+    assert_comm_axiom(ctx, s, g);
 
     Z3_parse_smtlib_string(ctx, 
                            "(benchmark tst :formula (forall (x Int) (y Int) (implies (= x y) (= (g x 0) (g 0 y)))))",
@@ -1672,8 +1733,9 @@ void parser_example3()
                            1, &g_name, &g);
     thm = Z3_get_smtlib_formula(ctx, 0);
     printf("formula: %s\n", Z3_ast_to_string(ctx, thm));
-    prove(ctx, thm, Z3_TRUE);
+    prove(ctx, s, thm, Z3_TRUE);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1718,6 +1780,7 @@ void parser_example4()
 void parser_example5() {
     Z3_config  cfg;
     Z3_context ctx = NULL;
+    Z3_solver s = NULL;
     int r;
 
     printf("\nparser_example5\n");
@@ -1727,6 +1790,7 @@ void parser_example5() {
     if (r == 0) {
         cfg = Z3_mk_config();
         ctx = mk_context_custom(cfg, throw_z3_error);
+        s   = mk_solver(ctx);
         Z3_del_config(cfg);
                 
         Z3_parse_smtlib_string(ctx, 
@@ -1735,12 +1799,14 @@ void parser_example5() {
                                0, 0, 0,
                                0, 0, 0);
         unreachable();
+	del_solver(ctx, s);
         Z3_del_context(ctx);
     }
     else {
-        printf("Z3 error: %s.\n", Z3_get_error_msg((Z3_error_code)r));
+      printf("Z3 error: %s.\n", Z3_get_error_msg_ex(ctx, (Z3_error_code)r));
         if (ctx != NULL) {
             printf("Error message: '%s'.\n",Z3_get_smtlib_error(ctx));
+	    del_solver(ctx, s);
             Z3_del_context(ctx);
         }
     }
@@ -1751,24 +1817,28 @@ void parser_example5() {
 */
 void numeral_example() {
     Z3_context ctx;
+    Z3_solver s;
     Z3_ast n1, n2;
     Z3_sort real_ty;
     printf("\nnumeral_example\n");
     LOG_MSG("numeral_example");
     
     ctx        = mk_context();
+    s          = mk_solver(ctx);
+
     real_ty    = Z3_mk_real_sort(ctx);
     n1 = Z3_mk_numeral(ctx, "1/2", real_ty);
     n2 = Z3_mk_numeral(ctx, "0.5", real_ty);
     printf("Numerals n1:%s", Z3_ast_to_string(ctx, n1));
     printf(" n2:%s\n", Z3_ast_to_string(ctx, n2));
-    prove(ctx, Z3_mk_eq(ctx, n1, n2), Z3_TRUE);
+    prove(ctx, s, Z3_mk_eq(ctx, n1, n2), Z3_TRUE);
 
     n1 = Z3_mk_numeral(ctx, "-1/3", real_ty);
     n2 = Z3_mk_numeral(ctx, "-0.33333333333333333333333333333333333333333333333333", real_ty);
     printf("Numerals n1:%s", Z3_ast_to_string(ctx, n1));
     printf(" n2:%s\n", Z3_ast_to_string(ctx, n2));
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, n1, n2)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, n1, n2)), Z3_TRUE);
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
  
@@ -1801,6 +1871,7 @@ void ite_example()
 */
 void enum_example() {
     Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort fruit;
     Z3_symbol name = Z3_mk_string_symbol(ctx, "fruit");
     Z3_symbol enum_names[3];
@@ -1831,14 +1902,14 @@ void enum_example() {
     orange = Z3_mk_app(ctx, enum_consts[2], 0, 0);
 
     /* Apples are different from oranges */
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, apple, orange)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, apple, orange)), Z3_TRUE);
 
     /* Apples pass the apple test */
-    prove(ctx, Z3_mk_app(ctx, enum_testers[0], 1, &apple), Z3_TRUE);
+    prove(ctx, s, Z3_mk_app(ctx, enum_testers[0], 1, &apple), Z3_TRUE);
 
     /* Oranges fail the apple test */
-    prove(ctx, Z3_mk_app(ctx, enum_testers[0], 1, &orange), Z3_FALSE);
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_app(ctx, enum_testers[0], 1, &orange)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_app(ctx, enum_testers[0], 1, &orange), Z3_FALSE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_app(ctx, enum_testers[0], 1, &orange)), Z3_TRUE);
 
     fruity = mk_var(ctx, "fruity", fruit);
 
@@ -1847,9 +1918,10 @@ void enum_example() {
     ors[1] = Z3_mk_eq(ctx, fruity, banana);
     ors[2] = Z3_mk_eq(ctx, fruity, orange);
 
-    prove(ctx, Z3_mk_or(ctx, 3, ors), Z3_TRUE);
+    prove(ctx, s, Z3_mk_or(ctx, 3, ors), Z3_TRUE);
 
     /* delete logical context */
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1858,6 +1930,7 @@ void enum_example() {
 */
 void list_example() {
     Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort int_ty, int_list;
     Z3_func_decl nil_decl, is_nil_decl, cons_decl, is_cons_decl, head_decl, tail_decl;
     Z3_ast nil, l1, l2, x, y, u, v, fml, fml1;
@@ -1877,43 +1950,44 @@ void list_example() {
     l2 = mk_binary_app(ctx, cons_decl, mk_int(ctx, 2), nil);
 
     /* nil != cons(1, nil) */
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, l1)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, l1)), Z3_TRUE);
 
     /* cons(2,nil) != cons(1, nil) */
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, l1, l2)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, l1, l2)), Z3_TRUE);
 
     /* cons(x,nil) = cons(y, nil) => x = y */
     x = mk_var(ctx, "x", int_ty);
     y = mk_var(ctx, "y", int_ty);    
     l1 = mk_binary_app(ctx, cons_decl, x, nil);
 	l2 = mk_binary_app(ctx, cons_decl, y, nil);
-    prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
 
     /* cons(x,u) = cons(x, v) => u = v */
     u = mk_var(ctx, "u", int_list);
     v = mk_var(ctx, "v", int_list);    
     l1 = mk_binary_app(ctx, cons_decl, x, u);
 	l2 = mk_binary_app(ctx, cons_decl, y, v);
-    prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE);
-    prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
 
     /* is_nil(u) or is_cons(u) */
     ors[0] = Z3_mk_app(ctx, is_nil_decl, 1, &u);
     ors[1] = Z3_mk_app(ctx, is_cons_decl, 1, &u);
-    prove(ctx, Z3_mk_or(ctx, 2, ors), Z3_TRUE);
+    prove(ctx, s, Z3_mk_or(ctx, 2, ors), Z3_TRUE);
 
     /* occurs check u != cons(x,u) */    
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE);
 
     /* destructors: is_cons(u) => u = cons(head(u),tail(u)) */
     fml1 = Z3_mk_eq(ctx, u, mk_binary_app(ctx, cons_decl, mk_unary_app(ctx, head_decl, u), mk_unary_app(ctx, tail_decl, u)));
     fml = Z3_mk_implies(ctx, Z3_mk_app(ctx, is_cons_decl, 1, &u), fml1);
     printf("Formula %s\n", Z3_ast_to_string(ctx, fml));
-    prove(ctx, fml, Z3_TRUE);
+    prove(ctx, s, fml, Z3_TRUE);
 
-    prove(ctx, fml1, Z3_FALSE);
+    prove(ctx, s, fml1, Z3_FALSE);
 
     /* delete logical context */
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -1922,6 +1996,7 @@ void list_example() {
 */ 
 void tree_example() {
     Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort cell;
     Z3_func_decl nil_decl, is_nil_decl, cons_decl, is_cons_decl, car_decl, cdr_decl;
     Z3_ast nil, l1, l2, x, y, u, v, fml, fml1;
@@ -1957,7 +2032,7 @@ void tree_example() {
     l2 = mk_binary_app(ctx, cons_decl, l1, nil);
 
     /* nil != cons(nil, nil) */
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, l1)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, l1)), Z3_TRUE);
 
     /* cons(x,u) = cons(x, v) => u = v */
     u = mk_var(ctx, "u", cell);
@@ -1966,26 +2041,27 @@ void tree_example() {
     y = mk_var(ctx, "y", cell);    
     l1 = mk_binary_app(ctx, cons_decl, x, u);
     l2 = mk_binary_app(ctx, cons_decl, y, v);
-    prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE);
-    prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
 
     /* is_nil(u) or is_cons(u) */
     ors[0] = Z3_mk_app(ctx, is_nil_decl, 1, &u);
     ors[1] = Z3_mk_app(ctx, is_cons_decl, 1, &u);
-    prove(ctx, Z3_mk_or(ctx, 2, ors), Z3_TRUE);
+    prove(ctx, s, Z3_mk_or(ctx, 2, ors), Z3_TRUE);
 
     /* occurs check u != cons(x,u) */    
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE);
 
     /* destructors: is_cons(u) => u = cons(car(u),cdr(u)) */
     fml1 = Z3_mk_eq(ctx, u, mk_binary_app(ctx, cons_decl, mk_unary_app(ctx, car_decl, u), mk_unary_app(ctx, cdr_decl, u)));
     fml = Z3_mk_implies(ctx, Z3_mk_app(ctx, is_cons_decl, 1, &u), fml1);
     printf("Formula %s\n", Z3_ast_to_string(ctx, fml));
-    prove(ctx, fml, Z3_TRUE);
+    prove(ctx, s, fml, Z3_TRUE);
 
-    prove(ctx, fml1, Z3_FALSE);
+    prove(ctx, s, fml1, Z3_FALSE);
 
     /* delete logical context */
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 
 
@@ -2000,6 +2076,7 @@ void tree_example() {
 
 void forest_example() {
     Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort tree, forest;
     Z3_func_decl nil1_decl, is_nil1_decl, cons1_decl, is_cons1_decl, car1_decl, cdr1_decl;
     Z3_func_decl nil2_decl, is_nil2_decl, cons2_decl, is_cons2_decl, car2_decl, cdr2_decl;
@@ -2073,8 +2150,8 @@ void forest_example() {
 
 
     /* nil != cons(nil,nil) */
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil1, f1)), Z3_TRUE);
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil2, t1)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil1, f1)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil2, t1)), Z3_TRUE);
 
 
     /* cons(x,u) = cons(x, v) => u = v */
@@ -2084,18 +2161,19 @@ void forest_example() {
     y = mk_var(ctx, "y", tree);
     l1 = mk_binary_app(ctx, cons1_decl, x, u);
     l2 = mk_binary_app(ctx, cons1_decl, y, v);
-    prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE);
-    prove(ctx, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, u, v)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_implies(ctx, Z3_mk_eq(ctx,l1,l2), Z3_mk_eq(ctx, x, y)), Z3_TRUE);
 
     /* is_nil(u) or is_cons(u) */
     ors[0] = Z3_mk_app(ctx, is_nil1_decl, 1, &u);
     ors[1] = Z3_mk_app(ctx, is_cons1_decl, 1, &u);
-    prove(ctx, Z3_mk_or(ctx, 2, ors), Z3_TRUE);
+    prove(ctx, s, Z3_mk_or(ctx, 2, ors), Z3_TRUE);
 
     /* occurs check u != cons(x,u) */    
-    prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE);
+    prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, u, l1)), Z3_TRUE);
 
     /* delete logical context */
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -2108,6 +2186,7 @@ void forest_example() {
 */ 
 void binary_tree_example() {
     Z3_context ctx = mk_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_sort cell;
     Z3_func_decl 
         nil_decl, /* nil : BinTree   (constructor) */
@@ -2164,22 +2243,23 @@ void binary_tree_example() {
         Z3_ast node3    = Z3_mk_app(ctx, node_decl, 3, args3);
 
         /* prove that nil != node1 */
-        prove(ctx, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, node1)), Z3_TRUE);
+        prove(ctx, s, Z3_mk_not(ctx, Z3_mk_eq(ctx, nil, node1)), Z3_TRUE);
 
         /* prove that nil = left(node1) */
-        prove(ctx, Z3_mk_eq(ctx, nil, mk_unary_app(ctx, left_decl, node1)), Z3_TRUE);
+        prove(ctx, s, Z3_mk_eq(ctx, nil, mk_unary_app(ctx, left_decl, node1)), Z3_TRUE);
 
         /* prove that node1 = right(node3) */
-        prove(ctx, Z3_mk_eq(ctx, node1, mk_unary_app(ctx, right_decl, node3)), Z3_TRUE);
+        prove(ctx, s, Z3_mk_eq(ctx, node1, mk_unary_app(ctx, right_decl, node3)), Z3_TRUE);
 
         /* prove that !is-nil(node2) */
-        prove(ctx, Z3_mk_not(ctx, mk_unary_app(ctx, is_nil_decl, node2)), Z3_TRUE);
+        prove(ctx, s, Z3_mk_not(ctx, mk_unary_app(ctx, is_nil_decl, node2)), Z3_TRUE);
 
         /* prove that value(node2) >= 0 */
-        prove(ctx, Z3_mk_ge(ctx, mk_unary_app(ctx, value_decl, node2), mk_int(ctx, 0)), Z3_TRUE);
+        prove(ctx, s, Z3_mk_ge(ctx, mk_unary_app(ctx, value_decl, node2), mk_int(ctx, 0)), Z3_TRUE);
     }
 
     /* delete logical context */
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -2190,6 +2270,7 @@ void binary_tree_example() {
 */ 
 void unsat_core_and_proof_example() {
     Z3_context ctx = mk_proof_context();
+    Z3_solver s = mk_solver(ctx);
     Z3_ast pa = mk_bool_var(ctx, "PredA");
     Z3_ast pb = mk_bool_var(ctx, "PredB");
     Z3_ast pc = mk_bool_var(ctx, "PredC");
@@ -2210,49 +2291,53 @@ void unsat_core_and_proof_example() {
     Z3_ast g2[2] = { f2, p2 };
     Z3_ast g3[2] = { f3, p3 };
     Z3_ast g4[2] = { f4, p4 };    
-    Z3_ast core[4] = { 0, 0, 0, 0 };
-    unsigned core_size = 4;
-    Z3_ast proof;
-    Z3_model m      = 0;
     Z3_lbool result;
+    Z3_ast proof;
+    Z3_model m  = 0;
     unsigned i;
+    Z3_ast_vector core;
 
     printf("\nunsat_core_and_proof_example\n");
     LOG_MSG("unsat_core_and_proof_example");
     
-    Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g1));
-    Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g2));
-    Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g3));
-    Z3_assert_cnstr(ctx, Z3_mk_or(ctx, 2, g4));
+    Z3_solver_assert(ctx, s, Z3_mk_or(ctx, 2, g1));
+    Z3_solver_assert(ctx, s, Z3_mk_or(ctx, 2, g2));
+    Z3_solver_assert(ctx, s, Z3_mk_or(ctx, 2, g3));
+    Z3_solver_assert(ctx, s, Z3_mk_or(ctx, 2, g4));
 
-    result = Z3_check_assumptions(ctx, 4, assumptions, &m, &proof, &core_size, core);
+    result = Z3_solver_check_assumptions(ctx, s, 4, assumptions);
 
     switch (result) {
     case Z3_L_FALSE:
+        core = Z3_solver_get_unsat_core(ctx, s);
+        proof = Z3_solver_get_proof(ctx, s);
         printf("unsat\n");
         printf("proof: %s\n", Z3_ast_to_string(ctx, proof));
 
         printf("\ncore:\n");
-        for (i = 0; i < core_size; ++i) {
-			printf("%s\n", Z3_ast_to_string(ctx, core[i]));
+        for (i = 0; i < Z3_ast_vector_size(ctx, core); ++i) {
+	  printf("%s\n", Z3_ast_to_string(ctx, Z3_ast_vector_get(ctx, core, i)));
         }
         printf("\n");
         break;
     case Z3_L_UNDEF:
         printf("unknown\n");
         printf("potential model:\n");
+	m = Z3_solver_get_model(ctx, s);
+	if (m) Z3_model_inc_ref(ctx, m);
         display_model(ctx, stdout, m);
         break;
     case Z3_L_TRUE:
         printf("sat\n");
+	m = Z3_solver_get_model(ctx, s);
+	if (m) Z3_model_inc_ref(ctx, m);
         display_model(ctx, stdout, m);
         break;
     }
-    if (m) {
-        Z3_del_model(ctx, m);
-    }
 
     /* delete logical context */
+    if (m) Z3_model_dec_ref(ctx, m);
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -2264,6 +2349,7 @@ void unsat_core_and_proof_example() {
 */
 typedef struct {
     Z3_context m_context;
+  Z3_solver  m_solver;
     // IMPORTANT: the fields m_answer_literals, m_retracted and m_num_answer_literals must be saved/restored
     // if push/pop operations are performed on m_context.
     Z3_ast     m_answer_literals[MAX_RETRACTABLE_ASSERTIONS];
@@ -2279,6 +2365,7 @@ typedef Z3_ext_context_struct * Z3_ext_context;
 Z3_ext_context mk_ext_context() {
     Z3_ext_context ctx         = (Z3_ext_context) malloc(sizeof(Z3_ext_context_struct));
     ctx->m_context             = mk_context();
+    ctx->m_solver              = mk_solver(ctx->m_context);
     ctx->m_num_answer_literals = 0;
     return ctx;
 }
@@ -2287,6 +2374,7 @@ Z3_ext_context mk_ext_context() {
    \brief Delete the given logical context wrapper.
 */
 void del_ext_context(Z3_ext_context ctx) {
+    del_solver(ctx->m_context, ctx->m_solver);
     Z3_del_context(ctx->m_context);
     free(ctx);
 }
@@ -2313,7 +2401,7 @@ unsigned assert_retractable_cnstr(Z3_ext_context ctx, Z3_ast c) {
     // assert: c OR (not ans_lit)
     args[0] = c;
     args[1] = Z3_mk_not(ctx->m_context, ans_lit);
-    Z3_assert_cnstr(ctx->m_context, Z3_mk_or(ctx->m_context, 2, args));
+    Z3_solver_assert(ctx->m_context, ctx->m_solver, Z3_mk_or(ctx->m_context, 2, args));
     return result;
 }
 
@@ -2344,10 +2432,8 @@ Z3_lbool ext_check(Z3_ext_context ctx) {
     Z3_lbool result;
     unsigned num_assumptions = 0;
     Z3_ast assumptions[MAX_RETRACTABLE_ASSERTIONS];
-    Z3_ast core[MAX_RETRACTABLE_ASSERTIONS];
+    Z3_ast_vector core;
     unsigned core_size;
-    Z3_ast   dummy_proof = 0; // we don't care about the proof in this example.
-    Z3_model dummy_model = 0; // we don't care about the model in this example.
     unsigned i;
     for (i = 0; i < ctx->m_num_answer_literals; i++) {
         if (ctx->m_retracted[i] == Z3_FALSE) {
@@ -2358,15 +2444,18 @@ Z3_lbool ext_check(Z3_ext_context ctx) {
             num_assumptions ++;
         }
     }
-    result = Z3_check_assumptions(ctx->m_context, num_assumptions, assumptions, &dummy_model, &dummy_proof, &core_size, core);
+    result = Z3_solver_check_assumptions(ctx->m_context, ctx->m_solver, num_assumptions, assumptions);
     if (result == Z3_L_FALSE) {
         // Display the UNSAT core
         printf("unsat core: ");
+        core = Z3_solver_get_unsat_core(ctx->m_context, ctx->m_solver);
+        core_size = Z3_ast_vector_size(ctx->m_context, core);
         for (i = 0; i < core_size; i++) {
+
             // In this example, we display the core based on the assertion ids.
             unsigned j;
             for (j = 0; j < ctx->m_num_answer_literals; j++) {
-                if (core[i] == ctx->m_answer_literals[j]) {
+ 	        if (Z3_ast_vector_get(ctx->m_context, core, i) == ctx->m_answer_literals[j]) {
                     printf("%d ", j);
                     break;
                 }
@@ -2378,10 +2467,6 @@ Z3_lbool ext_check(Z3_ext_context ctx) {
         printf("\n");
     }
 
-    if (dummy_model) {
-        Z3_del_model(ctx->m_context, dummy_model);
-    }
-
     return result;
 }
 
@@ -2452,6 +2537,7 @@ void incremental_example1() {
 void reference_counter_example() {
     Z3_config cfg;
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort ty;
     Z3_ast x, y, x_xor_y;
     Z3_symbol sx, sy;
@@ -2465,6 +2551,8 @@ void reference_counter_example() {
     // Z3_ast reference counters.
     ctx                = Z3_mk_context_rc(cfg);
     Z3_del_config(cfg); 
+    s                  = mk_solver(ctx);
+    Z3_solver_inc_ref(ctx, s);
 
     ty      = Z3_mk_bool_sort(ctx);
     Z3_inc_ref(ctx, Z3_sort_to_ast(ctx, ty)); // Z3_sort_to_ast(ty) is just syntax sugar for ((Z3_ast) ty)
@@ -2482,17 +2570,19 @@ void reference_counter_example() {
     // x and y are not needed anymore.
     Z3_dec_ref(ctx, x); 
     Z3_dec_ref(ctx, y);
-    Z3_assert_cnstr(ctx, x_xor_y);
+    Z3_solver_assert(ctx, s, x_xor_y);
     // x_or_y is not needed anymore.
     Z3_dec_ref(ctx, x_xor_y); 
     
     printf("model for: x xor y\n");
-    check(ctx, Z3_L_TRUE);
+    check(ctx, s, Z3_L_TRUE);
 
     // Test push & pop
-    Z3_push(ctx);
-    Z3_pop(ctx, 1);
+    Z3_solver_push(ctx, s);
+    Z3_solver_pop(ctx, s, 1);
+    Z3_solver_dec_ref(ctx, s);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 
@@ -2608,6 +2698,7 @@ void substitute_vars_example() {
 void fpa_example() {
     Z3_config cfg;
     Z3_context ctx;
+    Z3_solver s;
     Z3_sort double_sort, rm_sort;
     Z3_symbol s_rm, s_x, s_y, s_x_plus_y;
     Z3_ast rm, x, y, n, x_plus_y, c1, c2, c3, c4, c5;
@@ -2618,6 +2709,7 @@ void fpa_example() {
         
     cfg = Z3_mk_config();
     ctx = Z3_mk_context(cfg);
+    s   = mk_solver(ctx);
     Z3_del_config(cfg);
 
     double_sort = Z3_mk_fpa_sort(ctx, 11, 53);
@@ -2652,10 +2744,10 @@ void fpa_example() {
 	c4 = Z3_mk_and(ctx, 2, (Z3_ast*)&args3);
         
 	printf("c4: %s\n", Z3_ast_to_string(ctx, c4));
-	Z3_push(ctx);                  
-	Z3_assert_cnstr(ctx, c4);
-	check(ctx, Z3_L_TRUE);
-	Z3_pop(ctx, 1);
+	Z3_solver_push(ctx, s);                  
+	Z3_solver_assert(ctx, s, c4);
+	check(ctx, s, Z3_L_TRUE);
+	Z3_solver_pop(ctx, s, 1);
 
 	// Show that the following are equal:
 	//   (fp #b0 #b10000000001 #xc000000000000) 
@@ -2663,7 +2755,7 @@ void fpa_example() {
 	//   ((_ to_fp 11 53) RTZ 1.75 2)))
 	//   ((_ to_fp 11 53) RTZ 7.0)))
 	
-	Z3_push(ctx);
+	Z3_solver_push(ctx, s);
 	c1 = Z3_mk_fpa_fp(ctx, 
 					  Z3_mk_numeral(ctx, "0", Z3_mk_bv_sort(ctx, 1)),
 					  Z3_mk_numeral(ctx, "3377699720527872", Z3_mk_bv_sort(ctx, 52)),
@@ -2686,10 +2778,11 @@ void fpa_example() {
 	c5 = Z3_mk_and(ctx, 3, args3);
 
 	printf("c5: %s\n", Z3_ast_to_string(ctx, c5));
-	Z3_assert_cnstr(ctx, c5);
-	check(ctx, Z3_L_TRUE);
-	Z3_pop(ctx, 1);
+	Z3_solver_assert(ctx, s, c5);
+	check(ctx, s, Z3_L_TRUE);
+	Z3_solver_pop(ctx, s, 1);
 
+    del_solver(ctx, s);
     Z3_del_context(ctx);
 }
 

From 1575dd06a73e5dcdcdec57f41713d38126f49ab2 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Wed, 18 Nov 2015 09:42:12 -0800
Subject: [PATCH 12/14] expose labels from optimization. Move printing of
 objectives to after sat/unsat. Cahnge format to something that is somewhat
 related to how other output is created. Issue #325.

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/cmd_context/cmd_context.cpp | 10 ++++++----
 src/opt/opt_context.cpp         | 14 ++++++++++++--
 src/opt/opt_context.h           |  2 +-
 3 files changed, 19 insertions(+), 7 deletions(-)

diff --git a/src/cmd_context/cmd_context.cpp b/src/cmd_context/cmd_context.cpp
index b018d62c5..6e443d476 100644
--- a/src/cmd_context/cmd_context.cpp
+++ b/src/cmd_context/cmd_context.cpp
@@ -1401,9 +1401,10 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
     unsigned rlimit  = m_params.m_rlimit;
     scoped_watch sw(*this);
     lbool r;
+    bool was_pareto = false, was_opt = false;
 
     if (m_opt && !m_opt->empty()) {
-        bool was_pareto = false;
+        was_opt = true;
         m_check_sat_result = get_opt();
         cancel_eh<opt_wrapper> eh(*get_opt());
         scoped_ctrl_c ctrlc(eh);
@@ -1436,9 +1437,6 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
             r = l_true;
         }
         get_opt()->set_status(r);
-        if (r != l_false && !was_pareto) {
-            get_opt()->display_assignment(regular_stream());
-        }
     }
     else if (m_solver) {
         m_check_sat_result = m_solver.get(); // solver itself stores the result.
@@ -1465,6 +1463,10 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
     }
     display_sat_result(r);
     validate_check_sat_result(r);
+    if (was_opt && r != l_false && !was_pareto) {
+        get_opt()->display_assignment(regular_stream());
+    }
+
     if (r == l_true) {
         validate_model();
         if (m_params.m_dump_models) {
diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp
index 1b4b1e7bc..265e3b7c8 100644
--- a/src/opt/opt_context.cpp
+++ b/src/opt/opt_context.cpp
@@ -167,6 +167,12 @@ namespace opt {
         m_hard_constraints.reset();
     }
 
+    void context::get_labels(svector<symbol> & r) {
+        if (m_solver) {
+            m_solver->get_labels(r);
+        }
+    }
+
     void context::set_hard_constraints(ptr_vector<expr>& fmls) {
         if (m_scoped_state.set(fmls)) {
             clear_state();
@@ -1121,16 +1127,20 @@ namespace opt {
     }
 
     void context::display_assignment(std::ostream& out) {
+        out << "(objectives\n";
         for (unsigned i = 0; i < m_scoped_state.m_objectives.size(); ++i) {
             objective const& obj = m_scoped_state.m_objectives[i];
+            out << " (";
             display_objective(out, obj);
             if (get_lower_as_num(i) != get_upper_as_num(i)) {
-                out << " |-> [" << get_lower(i) << ":" << get_upper(i) << "]\n";
+                out << "  (" << get_lower(i) << " " << get_upper(i) << ")";
             }
             else {
-                out << " |-> " << get_lower(i) << "\n";
+                out << " " << get_lower(i);
             }
+            out << ")\n";
         }
+        out << ")\n";
     }
 
     void context::display_objective(std::ostream& out, objective const& obj) const {
diff --git a/src/opt/opt_context.h b/src/opt/opt_context.h
index 735dc6905..b364fe63e 100644
--- a/src/opt/opt_context.h
+++ b/src/opt/opt_context.h
@@ -184,7 +184,7 @@ namespace opt {
         virtual void fix_model(model_ref& _m);
         virtual void collect_statistics(statistics& stats) const;
         virtual proof* get_proof() { return 0; }
-        virtual void get_labels(svector<symbol> & r) {}
+        virtual void get_labels(svector<symbol> & r);
         virtual void get_unsat_core(ptr_vector<expr> & r) {}
         virtual std::string reason_unknown() const;
 

From 9cba63c31f6f1466dd4ef442bb840d1ab84539c7 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Wed, 18 Nov 2015 12:32:15 -0800
Subject: [PATCH 13/14] remove deprecated iz3 example. Remove deprecated
 process control

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 examples/interp/iz3.cpp | 458 ----------------------------------------
 scripts/mk_project.py   |   1 -
 src/api/api_context.cpp |   4 +-
 src/util/util.cpp       |  21 --
 src/util/util.h         |   1 -
 5 files changed, 1 insertion(+), 484 deletions(-)
 delete mode 100755 examples/interp/iz3.cpp

diff --git a/examples/interp/iz3.cpp b/examples/interp/iz3.cpp
deleted file mode 100755
index 21ea518a6..000000000
--- a/examples/interp/iz3.cpp
+++ /dev/null
@@ -1,458 +0,0 @@
-
-/*++
-Copyright (c) 2015 Microsoft Corporation
-
---*/
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <iostream>
-#include <string>
-#include <vector>
-#include "z3.h"
-
-
-
-int usage(const char **argv){
-  std::cerr << "usage: " << argv[0] << " [options] file.smt" << std::endl;
-  std::cerr << std::endl;
-  std::cerr << "options:" << std::endl;
-  std::cerr << "  -t,--tree        tree interpolation" << std::endl;
-  std::cerr << "  -c,--check       check result" << std::endl;
-  std::cerr << "  -p,--profile     profile execution" << std::endl;
-  std::cerr << "  -w,--weak        weak interpolants" << std::endl;
-  std::cerr << "  -f,--flat        ouput flat formulas" << std::endl;
-  std::cerr << "  -o <file>        ouput to SMT-LIB file" << std::endl;
-  std::cerr << "  -a,--anon        anonymize" << std::endl;
-  std::cerr << "  -s,--simple      simple proof mode" << std::endl;
-  std::cerr << std::endl;
-  return 1;
-}
-
-int main(int argc, const char **argv) {
-    
-  bool tree_mode = false;
-  bool check_mode = false;
-  bool profile_mode = false;
-  bool incremental_mode = false;
-  std::string output_file;
-  bool flat_mode = false;
-  bool anonymize = false;
-  bool write = false;
-
-  Z3_config cfg = Z3_mk_config();
-  // Z3_interpolation_options options = Z3_mk_interpolation_options();
-  // Z3_params options = 0;
-
-  /* Parse the command line */
-  int argn = 1;
-  while(argn < argc-1){
-    std::string flag = argv[argn];
-    if(flag[0] == '-'){
-      if(flag == "-t" || flag == "--tree")
-	tree_mode = true;
-      else if(flag == "-c" || flag == "--check")
-	check_mode = true;
-      else if(flag == "-p" || flag == "--profile")
-	profile_mode = true;
-#if 0
-      else if(flag == "-w" || flag == "--weak")
-        Z3_set_interpolation_option(options,"weak","1");
-      else if(flag == "--secondary")
-        Z3_set_interpolation_option(options,"secondary","1");
-#endif
-      else if(flag == "-i" || flag == "--incremental")
-        incremental_mode = true;
-      else if(flag == "-o"){
-        argn++;
-        if(argn >= argc) return usage(argv);
-        output_file = argv[argn];
-      }
-      else if(flag == "-f" || flag == "--flat")
-        flat_mode = true;
-      else if(flag == "-a" || flag == "--anon")
-        anonymize = true;
-      else if(flag == "-w" || flag == "--write")
-        write = true;
-      else if(flag == "-s" || flag == "--simple")
-        Z3_set_param_value(cfg,"PREPROCESS","false");
-      else
-        return usage(argv);
-    }
-    argn++;
-  }
-  if(argn != argc-1)
-    return usage(argv);
-  const char *filename = argv[argn];
-
-
-  /* Create a Z3 context to contain formulas */
-  Z3_context ctx = Z3_mk_interpolation_context(cfg);
-
-  if(write || anonymize)
-    Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB2_COMPLIANT);
-  else if(!flat_mode)
-    Z3_set_ast_print_mode(ctx,Z3_PRINT_SMTLIB_COMPLIANT);
-  
-  /* Read an interpolation problem */
-
-  unsigned num;
-  Z3_ast *constraints;
-  unsigned *parents = 0;
-  const char *error;
-  bool ok;
-  unsigned num_theory;
-  Z3_ast *theory;
-
-  ok = Z3_read_interpolation_problem(ctx, &num, &constraints, tree_mode ? &parents : 0, filename, &error, &num_theory, &theory) != 0;
-
-  /* If parse failed, print the error message */
-
-  if(!ok){
-    std::cerr << error << "\n";
-    return 1;
-  }
-
-  /* if we get only one formula, and it is a conjunction, split it into conjuncts. */
-  if(!tree_mode && num == 1){
-    Z3_app app = Z3_to_app(ctx,constraints[0]);
-    Z3_func_decl func = Z3_get_app_decl(ctx,app);
-    Z3_decl_kind dk = Z3_get_decl_kind(ctx,func);
-    if(dk == Z3_OP_AND){
-      int nconjs = Z3_get_app_num_args(ctx,app);
-      if(nconjs > 1){
-	std::cout << "Splitting formula into " << nconjs << " conjuncts...\n";
-	num = nconjs;
-	constraints = new Z3_ast[num];
-	for(unsigned k = 0; k < num; k++)
-	  constraints[k] = Z3_get_app_arg(ctx,app,k);
-      }
-    }
-  }
-
-  /* Write out anonymized version. */
-
-  if(write || anonymize){
-#if 0
-    Z3_anonymize_ast_vector(ctx,num,constraints);
-#endif
-    std::string ofn = output_file.empty() ? "iz3out.smt2" : output_file;
-    Z3_write_interpolation_problem(ctx, num, constraints, parents, ofn.c_str(), num_theory,  theory);
-    std::cout << "anonymized problem written to " << ofn << "\n";
-    exit(0);
-  }
-
-  /* Compute an interpolant, or get a model. */
-
-  Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));
-  Z3_model model = 0;
-  Z3_lbool result;
-
-  if(!incremental_mode){
-    /* In non-incremental mode, we just pass the constraints. */
-      result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, constraints, parents,  options, interpolants, &model, 0, false, num_theory, theory);
-  }
-  else {
-
-    /* This is a somewhat useless demonstration of incremental mode.
-      Here, we assert the constraints in the context, then pass them to
-      iZ3 in an array, so iZ3 knows the sequence. Note it's safe to pass
-      "true", even though we haven't techically asserted if. */
-
-    Z3_push(ctx);
-    std::vector<Z3_ast> asserted(num);
-
-    /* We start with nothing asserted. */
-    for(unsigned i = 0; i < num; i++)
-      asserted[i] = Z3_mk_true(ctx);
-
-    /* Now we assert the constrints one at a time until UNSAT. */
-
-    for(unsigned i = 0; i < num; i++){
-      asserted[i] = constraints[i];
-      Z3_assert_cnstr(ctx,constraints[i]);  // assert one constraint
-      result = Z3_L_UNDEF; // FIXME: Z3_interpolate(ctx, num, &asserted[0], parents,  options, interpolants, &model, 0, true, 0, 0);
-      if(result == Z3_L_FALSE){
-	for(unsigned j = 0; j < num-1; j++)
-          /* Since we want the interpolant formulas to survive a "pop", we
-            "persist" them here. */
-          Z3_persist_ast(ctx,interpolants[j],1);
-        break;
-      }
-    }
-    Z3_pop(ctx,1);
-  }
-  
-  switch (result) {
-  
-    /* If UNSAT, print the interpolants */
-  case Z3_L_FALSE:
-    printf("unsat\n");
-    if(output_file.empty()){
-      printf("interpolant:\n");
-      for(unsigned i = 0; i < num-1; i++)
-        printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
-    }
-    else {
-#if 0
-      Z3_write_interpolation_problem(ctx,num-1,interpolants,0,output_file.c_str());
-      printf("interpolant written to %s\n",output_file.c_str());
-#endif
-    }
-#if 1
-    if(check_mode){
-      std::cout << "Checking interpolant...\n";
-      bool chk;
-      chk = Z3_check_interpolant(ctx,num,constraints,parents,interpolants,&error,num_theory,theory) != 0;
-      if(chk)
-	std::cout << "Interpolant is correct\n";
-      else {
-        std::cout << "Interpolant is incorrect\n";
-        std::cout << error;
-        return 1;
-      }
-    }
-#endif
-    break;
-  case Z3_L_UNDEF:
-    printf("fail\n");
-    break;
-  case Z3_L_TRUE:
-    printf("sat\n");
-    printf("model:\n%s\n", Z3_model_to_string(ctx, model));
-    break;
-  }
-
-  if(profile_mode)
-    std::cout << Z3_interpolation_profile(ctx);
-
-  /* Delete the model if there is one */
-  
-  if (model)
-    Z3_del_model(ctx, model);
-  
-  /* Delete logical context. */
-
-  Z3_del_context(ctx);
-  free(interpolants);
-
-  return 0;
-}
-
-
-#if 0
-
-
-
-int test(){
-  int i;
-
-  /* Create a Z3 context to contain formulas */
-
-  Z3_config cfg = Z3_mk_config();
-  Z3_context ctx = iz3_mk_context(cfg);
-    
-  int num = 2;
-
-  Z3_ast *constraints = (Z3_ast *)malloc(num * sizeof(Z3_ast));
-
-#if 1
-  Z3_sort arr = Z3_mk_array_sort(ctx,Z3_mk_int_sort(ctx),Z3_mk_bool_sort(ctx)); 
-  Z3_symbol  as  = Z3_mk_string_symbol(ctx, "a");
-  Z3_symbol  bs  = Z3_mk_string_symbol(ctx, "b");
-  Z3_symbol  xs  = Z3_mk_string_symbol(ctx, "x");
-
-  Z3_ast a = Z3_mk_const(ctx,as,arr);
-  Z3_ast b = Z3_mk_const(ctx,bs,arr);
-  Z3_ast x = Z3_mk_const(ctx,xs,Z3_mk_int_sort(ctx));
-  
-  Z3_ast c1 = Z3_mk_eq(ctx,a,Z3_mk_store(ctx,b,x,Z3_mk_true(ctx)));
-  Z3_ast c2 = Z3_mk_not(ctx,Z3_mk_select(ctx,a,x));
-#else
-  Z3_symbol  xs  = Z3_mk_string_symbol(ctx, "x");
-  Z3_ast x = Z3_mk_const(ctx,xs,Z3_mk_bool_sort(ctx));
-  Z3_ast c1 = Z3_mk_eq(ctx,x,Z3_mk_true(ctx));
-  Z3_ast c2 = Z3_mk_eq(ctx,x,Z3_mk_false(ctx));
-
-#endif
-
-  constraints[0] = c1;
-  constraints[1] = c2;
-  
-  /* print out the result for grins. */
-
-  // Z3_string smtout = Z3_benchmark_to_smtlib_string (ctx, "foo", "QFLIA", "sat", "", num, constraints, Z3_mk_true(ctx));
-
-  // Z3_string smtout = Z3_ast_to_string(ctx,constraints[0]);
-  // Z3_string smtout = Z3_context_to_string(ctx);
-  // puts(smtout);
-
-  iz3_print(ctx,num,constraints,"iZ3temp.smt");
-
-  /* Make room for interpolants. */
-
-  Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));
-
-  /* Make room for the model. */
-
-  Z3_model model = 0;
-
-  /* Call the prover */
-
-  Z3_lbool result = iz3_interpolate(ctx, num, constraints, interpolants, &model);
-
-  switch (result) {
-  
-    /* If UNSAT, print the interpolants */
-  case Z3_L_FALSE:
-    printf("unsat, interpolants:\n");
-    for(i = 0; i < num-1; i++)
-      printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
-    break;
-  case Z3_L_UNDEF:
-    printf("fail\n");
-    break;
-  case Z3_L_TRUE:
-    printf("sat\n");
-    printf("model:\n%s\n", Z3_model_to_string(ctx, model));
-    break;
-  }
-
-  /* Delete the model if there is one */
-  
-  if (model)
-    Z3_del_model(ctx, model);
-  
-  /* Delete logical context (note, we call iz3_del_context, not
-     Z3_del_context */
-
-  iz3_del_context(ctx);
-
-  return 1;
-}
-
-struct z3_error {
-  Z3_error_code c;
-  z3_error(Z3_error_code _c) : c(_c) {}
-};
-
-extern "C" {
-  static void throw_z3_error(Z3_error_code c){
-    throw z3_error(c);
-  }
-}
-
-int main(int argc, const char **argv) {
-
-  /* Create a Z3 context to contain formulas */
-
-  Z3_config cfg = Z3_mk_config();
-  Z3_context ctx = iz3_mk_context(cfg);
-  Z3_set_error_handler(ctx, throw_z3_error);
-    
-  /* Make some constraints, by parsing an smtlib formatted file given as arg 1 */
-
-  try {
-    Z3_parse_smtlib_file(ctx, argv[1], 0, 0, 0, 0, 0, 0);
-  }
-  catch(const z3_error &err){
-    std::cerr << "Z3 error: " << Z3_get_error_msg(err.c) << "\n";
-    std::cerr << Z3_get_smtlib_error(ctx) << "\n";
-    return(1);
-  } 
-
-  /* Get the constraints from the parser. */
-
-  int num = Z3_get_smtlib_num_formulas(ctx);
-
-  if(num == 0){
-    std::cerr << "iZ3 error: File contains no formulas.\n";
-    return 1;
-  }
-
-
-  Z3_ast *constraints = (Z3_ast *)malloc(num * sizeof(Z3_ast));
-
-  int i;
-  for (i = 0; i < num; i++)
-    constraints[i] = Z3_get_smtlib_formula(ctx, i);
-
-  /* if we get only one formula, and it is a conjunction, split it into conjuncts. */
-  if(num == 1){
-    Z3_app app = Z3_to_app(ctx,constraints[0]);
-    Z3_func_decl func = Z3_get_app_decl(ctx,app);
-    Z3_decl_kind dk = Z3_get_decl_kind(ctx,func);
-    if(dk == Z3_OP_AND){
-      int nconjs = Z3_get_app_num_args(ctx,app);
-      if(nconjs > 1){
-	std::cout << "Splitting formula into " << nconjs << " conjuncts...\n";
-	num = nconjs;
-	constraints = new Z3_ast[num];
-	for(int k = 0; k < num; k++)
-	  constraints[k] = Z3_get_app_arg(ctx,app,k);
-      }
-    }
-  }
-
-
-  /* print out the result for grins. */
-
-  // Z3_string smtout = Z3_benchmark_to_smtlib_string (ctx, "foo", "QFLIA", "sat", "", num, constraints, Z3_mk_true(ctx));
-
-  // Z3_string smtout = Z3_ast_to_string(ctx,constraints[0]);
-  // Z3_string smtout = Z3_context_to_string(ctx);
-  // puts(smtout);
-
-  // iz3_print(ctx,num,constraints,"iZ3temp.smt");
-
-  /* Make room for interpolants. */
-
-  Z3_ast *interpolants = (Z3_ast *)malloc((num-1) * sizeof(Z3_ast));
-
-  /* Make room for the model. */
-
-  Z3_model model = 0;
-
-  /* Call the prover */
-
-  Z3_lbool result = iz3_interpolate(ctx, num, constraints, interpolants, &model);
-
-  switch (result) {
-  
-    /* If UNSAT, print the interpolants */
-  case Z3_L_FALSE:
-    printf("unsat, interpolants:\n");
-    for(i = 0; i < num-1; i++)
-      printf("%s\n", Z3_ast_to_string(ctx, interpolants[i]));
-    std::cout << "Checking interpolants...\n";
-    const char *error;
-    if(iZ3_check_interpolant(ctx, num, constraints, 0, interpolants, &error))
-      std::cout << "Interpolant is correct\n";
-    else {
-      std::cout << "Interpolant is incorrect\n";
-      std::cout << error << "\n";
-    }
-    break;
-  case Z3_L_UNDEF:
-    printf("fail\n");
-    break;
-  case Z3_L_TRUE:
-    printf("sat\n");
-    printf("model:\n%s\n", Z3_model_to_string(ctx, model));
-    break;
-  }
-
-  /* Delete the model if there is one */
-  
-  if (model)
-    Z3_del_model(ctx, model);
-  
-  /* Delete logical context (note, we call iz3_del_context, not
-     Z3_del_context */
-
-  iz3_del_context(ctx);
-
-  return 0;
-}
-
-#endif
diff --git a/scripts/mk_project.py b/scripts/mk_project.py
index 2863de628..dfe801bdd 100644
--- a/scripts/mk_project.py
+++ b/scripts/mk_project.py
@@ -94,7 +94,6 @@ def init_project_def():
     set_z3py_dir('api/python')
     # Examples
     add_cpp_example('cpp_example', 'c++') 
-    add_cpp_example('iz3', 'interp') 
     add_cpp_example('z3_tptp', 'tptp') 
     add_c_example('c_example', 'c')
     add_c_example('maxsat')
diff --git a/src/api/api_context.cpp b/src/api/api_context.cpp
index f17a296fa..6749f1525 100644
--- a/src/api/api_context.cpp
+++ b/src/api/api_context.cpp
@@ -103,9 +103,7 @@ namespace api {
 
         m_smtlib_parser           = 0;
         m_smtlib_parser_has_decls = false;
-        
-        z3_bound_num_procs();
-        
+                
         m_error_handler = &default_error_handler;
 
         m_basic_fid = m().get_basic_family_id();
diff --git a/src/util/util.cpp b/src/util/util.cpp
index c4b729adb..bfd4923a8 100644
--- a/src/util/util.cpp
+++ b/src/util/util.cpp
@@ -151,24 +151,3 @@ void escaped::display(std::ostream & out) const {
     }
 }
 
-#ifdef _WINDOWS
-#ifdef ARRAYSIZE
-#undef ARRAYSIZE
-#endif
-#include <windows.h>
-#endif
-
-void z3_bound_num_procs() {
-
-#ifdef _Z3_COMMERCIAL
-#define Z3_COMMERCIAL_MAX_CORES 4
-#ifdef _WINDOWS
-    DWORD_PTR numProcs = (1 << Z3_COMMERCIAL_MAX_CORES) - 1;
-    SetProcessAffinityMask(GetCurrentProcess(), numProcs);
-#endif
-#else
-    // Not bounded: Research evaluations are 
-    // not reasonable if run with artificial 
-    // or hidden throttles.
-#endif
-}
diff --git a/src/util/util.h b/src/util/util.h
index f97f5c1f9..1e15b526c 100644
--- a/src/util/util.h
+++ b/src/util/util.h
@@ -400,7 +400,6 @@ inline size_t megabytes_to_bytes(unsigned mb) {
     return r;
 }
 
-void z3_bound_num_procs();
 
 #endif /* UTIL_H_ */
 

From c58e640563424747ecf086339aeb2f6437b46567 Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Wed, 18 Nov 2015 14:53:08 -0800
Subject: [PATCH 14/14] extract labels for optimal model. Fix to #325

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/opt/maxsmt.cpp                    |  5 +++--
 src/opt/maxsmt.h                      | 10 ++++++----
 src/opt/opt_context.cpp               | 16 +++++-----------
 src/opt/opt_context.h                 |  2 +-
 src/opt/opt_pareto.cpp                |  2 ++
 src/opt/opt_pareto.h                  |  5 +++--
 src/opt/optsmt.cpp                    |  9 +++++++--
 src/opt/optsmt.h                      |  3 ++-
 src/sat/sat_solver/inc_sat_solver.cpp |  1 -
 9 files changed, 29 insertions(+), 24 deletions(-)

diff --git a/src/opt/maxsmt.cpp b/src/opt/maxsmt.cpp
index 1bb521923..cb598617c 100644
--- a/src/opt/maxsmt.cpp
+++ b/src/opt/maxsmt.cpp
@@ -191,7 +191,7 @@ namespace opt {
             m_msolver->set_adjust_value(m_adjust_value);
             is_sat = (*m_msolver)();
             if (is_sat != l_false) {
-                m_msolver->get_model(m_model);
+                m_msolver->get_model(m_model, m_labels);
             }
         }
 
@@ -247,8 +247,9 @@ namespace opt {
         m_upper = r;
     }    
 
-    void maxsmt::get_model(model_ref& mdl) {
+    void maxsmt::get_model(model_ref& mdl, svector<symbol>& labels) {
         mdl = m_model.get();
+        labels = m_labels;
     }
 
     void maxsmt::commit_assignment() {
diff --git a/src/opt/maxsmt.h b/src/opt/maxsmt.h
index 8d290a640..7dbf763e2 100644
--- a/src/opt/maxsmt.h
+++ b/src/opt/maxsmt.h
@@ -46,7 +46,7 @@ namespace opt {
         virtual bool get_assignment(unsigned index) const = 0;
         virtual void set_cancel(bool f) = 0;
         virtual void collect_statistics(statistics& st) const = 0;
-        virtual void get_model(model_ref& mdl) = 0;
+        virtual void get_model(model_ref& mdl, svector<symbol>& labels) = 0;
         virtual void updt_params(params_ref& p) = 0;
         void set_adjust_value(adjust_value& adj) { m_adjust_value = adj; }
 
@@ -67,6 +67,7 @@ namespace opt {
         rational         m_lower;
         rational         m_upper;
         model_ref        m_model;
+        svector<symbol>  m_labels;
         svector<bool>    m_assignment;       // truth assignment to soft constraints
         params_ref       m_params;           // config
 
@@ -79,9 +80,9 @@ namespace opt {
         virtual bool get_assignment(unsigned index) const { return m_assignment[index]; }
         virtual void set_cancel(bool f) { m_cancel = f; if (f) s().cancel(); else s().reset_cancel(); }
         virtual void collect_statistics(statistics& st) const { }
-        virtual void get_model(model_ref& mdl) { mdl = m_model.get(); }
+        virtual void get_model(model_ref& mdl, svector<symbol>& labels) { mdl = m_model.get(); labels = m_labels;}
         virtual void commit_assignment();
-        void set_model() { s().get_model(m_model); }
+        void set_model() { s().get_model(m_model); s().get_labels(m_labels); }
         virtual void updt_params(params_ref& p);
         solver& s();
         void init();
@@ -122,6 +123,7 @@ namespace opt {
         rational         m_upper;
         adjust_value     m_adjust_value;
         model_ref        m_model;
+        svector<symbol>  m_labels;
         params_ref       m_params;
     public:
         maxsmt(maxsat_context& c);
@@ -139,7 +141,7 @@ namespace opt {
         rational get_upper() const;        
         void update_lower(rational const& r);
         void update_upper(rational const& r);
-        void get_model(model_ref& mdl);
+        void get_model(model_ref& mdl, svector<symbol>& labels);
         bool get_assignment(unsigned index) const;
         void display_answer(std::ostream& out) const;        
         void collect_statistics(statistics& st) const;
diff --git a/src/opt/opt_context.cpp b/src/opt/opt_context.cpp
index 265e3b7c8..1b33c2cf1 100644
--- a/src/opt/opt_context.cpp
+++ b/src/opt/opt_context.cpp
@@ -168,9 +168,7 @@ namespace opt {
     }
 
     void context::get_labels(svector<symbol> & r) {
-        if (m_solver) {
-            m_solver->get_labels(r);
-        }
+        r.append(m_labels);
     }
 
     void context::set_hard_constraints(ptr_vector<expr>& fmls) {
@@ -234,6 +232,7 @@ namespace opt {
         TRACE("opt", tout << "initial search result: " << is_sat << "\n";);
         if (is_sat != l_false) {
             s.get_model(m_model);
+            s.get_labels(m_labels);
         }
         if (is_sat != l_true) {
             return is_sat;
@@ -282,11 +281,6 @@ namespace opt {
         }
     }
 
-    void context::set_model(model_ref& mdl) {
-        m_model = mdl;
-        fix_model(mdl);
-    }
-
     void context::get_model(model_ref& mdl) {
         mdl = m_model;
         fix_model(mdl);
@@ -295,7 +289,7 @@ namespace opt {
     lbool context::execute_min_max(unsigned index, bool committed, bool scoped, bool is_max) {
         if (scoped) get_solver().push();            
         lbool result = m_optsmt.lex(index, is_max);
-        if (result == l_true) m_optsmt.get_model(m_model);
+        if (result == l_true) m_optsmt.get_model(m_model, m_labels);
         if (scoped) get_solver().pop(1);        
         if (result == l_true && committed) m_optsmt.commit_assignment(index);
         return result;
@@ -306,7 +300,7 @@ namespace opt {
         maxsmt& ms = *m_maxsmts.find(id);
         if (scoped) get_solver().push();            
         lbool result = ms();
-        if (result != l_false && (ms.get_model(tmp), tmp.get())) ms.get_model(m_model);
+        if (result != l_false && (ms.get_model(tmp, m_labels), tmp.get())) ms.get_model(m_model, m_labels);
         if (scoped) get_solver().pop(1);
         if (result == l_true && committed) ms.commit_assignment();
         return result;
@@ -459,7 +453,7 @@ namespace opt {
     }
 
     void context::yield() {
-        m_pareto->get_model(m_model);
+        m_pareto->get_model(m_model, m_labels);
         update_bound(true);
         update_bound(false);
     }
diff --git a/src/opt/opt_context.h b/src/opt/opt_context.h
index b364fe63e..dc180e8e6 100644
--- a/src/opt/opt_context.h
+++ b/src/opt/opt_context.h
@@ -162,6 +162,7 @@ namespace opt {
         bool                         m_pp_neat;
         symbol                       m_maxsat_engine;
         symbol                       m_logic;
+        svector<symbol>              m_labels;
     public:
         context(ast_manager& m);
         virtual ~context();
@@ -180,7 +181,6 @@ namespace opt {
         virtual lbool optimize();
         virtual bool print_model() const;
         virtual void get_model(model_ref& _m);
-        virtual void set_model(model_ref& _m);
         virtual void fix_model(model_ref& _m);
         virtual void collect_statistics(statistics& stats) const;
         virtual proof* get_proof() { return 0; }
diff --git a/src/opt/opt_pareto.cpp b/src/opt/opt_pareto.cpp
index 5e1d4b269..dea744a72 100644
--- a/src/opt/opt_pareto.cpp
+++ b/src/opt/opt_pareto.cpp
@@ -38,6 +38,7 @@ namespace opt {
                         return l_undef;
                     }
                     m_solver->get_model(m_model);
+                    m_solver->get_labels(m_labels);
                     IF_VERBOSE(1,
                                model_ref mdl(m_model);
                                cb.fix_model(mdl); 
@@ -96,6 +97,7 @@ namespace opt {
         }
         if (is_sat == l_true) {
             m_solver->get_model(m_model);
+            m_solver->get_labels(m_labels);
             mk_not_dominated_by();
         }
         return is_sat;
diff --git a/src/opt/opt_pareto.h b/src/opt/opt_pareto.h
index 88a3ce9c1..122f29c55 100644
--- a/src/opt/opt_pareto.h
+++ b/src/opt/opt_pareto.h
@@ -31,7 +31,6 @@ namespace opt {
         virtual expr_ref mk_gt(unsigned i, model_ref& model) = 0;
         virtual expr_ref mk_ge(unsigned i, model_ref& model) = 0;
         virtual expr_ref mk_le(unsigned i, model_ref& model) = 0;
-        virtual void set_model(model_ref& m) = 0;
         virtual void fix_model(model_ref& m) = 0;
     };
     class pareto_base {
@@ -42,6 +41,7 @@ namespace opt {
         ref<solver>      m_solver;
         params_ref       m_params;
         model_ref        m_model;
+        svector<symbol>  m_labels;
     public:
         pareto_base(
             ast_manager & m, 
@@ -77,8 +77,9 @@ namespace opt {
         }
         virtual lbool operator()() = 0;
 
-        virtual void get_model(model_ref& mdl) {
+        virtual void get_model(model_ref& mdl, svector<symbol>& labels) {
             mdl = m_model;
+            labels = m_labels;
         }
 
     protected:
diff --git a/src/opt/optsmt.cpp b/src/opt/optsmt.cpp
index 02effa337..c9ee61ebc 100644
--- a/src/opt/optsmt.cpp
+++ b/src/opt/optsmt.cpp
@@ -51,6 +51,7 @@ namespace opt {
             if (src[i] >= dst[i]) {
                 dst[i] = src[i];
                 m_models.set(i, m_s->get_model(i));
+                m_s->get_labels(m_labels);
                 m_lower_fmls[i] = fmls[i].get();
                 if (dst[i].is_pos() && !dst[i].is_finite()) { // review: likely done already.
                     m_lower_fmls[i] = m.mk_false();
@@ -156,7 +157,8 @@ namespace opt {
                 if (is_sat == l_true) {
                     disj.reset();
                     m_s->maximize_objectives(disj);
-                    m_s->get_model(m_model);                   
+                    m_s->get_model(m_model);       
+                    m_s->get_labels(m_labels);            
                     for (unsigned i = 0; i < ors.size(); ++i) {
                         expr_ref tmp(m);
                         m_model->eval(ors[i].get(), tmp);
@@ -203,6 +205,7 @@ namespace opt {
     expr_ref optsmt::update_lower() {
         expr_ref_vector disj(m);
         m_s->get_model(m_model);
+        m_s->get_labels(m_labels);
         m_s->maximize_objectives(disj);
         set_max(m_lower, m_s->get_objective_values(), disj);
         TRACE("opt",
@@ -331,6 +334,7 @@ namespace opt {
             
             m_s->maximize_objective(obj_index, block);
             m_s->get_model(m_model);
+            m_s->get_labels(m_labels);
             inf_eps obj = m_s->saved_objective_value(obj_index);
             if (obj > m_lower[obj_index]) {
                 m_lower[obj_index] = obj;                
@@ -405,8 +409,9 @@ namespace opt {
         return m_upper[i];
     }
 
-    void optsmt::get_model(model_ref& mdl) {
+    void optsmt::get_model(model_ref& mdl, svector<symbol> & labels) {
         mdl = m_model.get();
+        labels = m_labels;
     }
 
     // force lower_bound(i) <= objective_value(i)    
diff --git a/src/opt/optsmt.h b/src/opt/optsmt.h
index 10ea9f11c..f4efa25f9 100644
--- a/src/opt/optsmt.h
+++ b/src/opt/optsmt.h
@@ -38,6 +38,7 @@ namespace opt {
         svector<smt::theory_var> m_vars;
         symbol           m_optsmt_engine;
         model_ref        m_model;
+        svector<symbol>  m_labels;
         sref_vector<model> m_models;
     public:
         optsmt(ast_manager& m): 
@@ -60,7 +61,7 @@ namespace opt {
         inf_eps get_lower(unsigned index) const;
         inf_eps get_upper(unsigned index) const;
         bool objective_is_model_valid(unsigned index) const;
-        void    get_model(model_ref& mdl);
+        void    get_model(model_ref& mdl, svector<symbol>& labels);
         model*  get_model(unsigned index) const { return m_models[index]; }
 
         void update_lower(unsigned idx, inf_eps const& r);
diff --git a/src/sat/sat_solver/inc_sat_solver.cpp b/src/sat/sat_solver/inc_sat_solver.cpp
index b0d771ba8..43b2c2e3f 100644
--- a/src/sat/sat_solver/inc_sat_solver.cpp
+++ b/src/sat/sat_solver/inc_sat_solver.cpp
@@ -250,7 +250,6 @@ public:
         return "no reason given";
     }
     virtual void get_labels(svector<symbol> & r) {
-        UNREACHABLE();
     }
     virtual unsigned get_num_assertions() const {
         return m_fmls.size();