From b3bd9b89b541bff02bdad7db735394cdf71cc53d Mon Sep 17 00:00:00 2001
From: Nikolaj Bjorner <nbjorner@microsoft.com>
Date: Fri, 17 Nov 2017 19:55:23 -0800
Subject: [PATCH] prepare for inverse model conversion for formulas

Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
---
 src/sat/tactic/goal2sat.cpp                   | 15 ++-
 src/solver/solver.cpp                         | 13 ++-
 src/tactic/bv/bit_blaster_model_converter.cpp | 31 ++++--
 src/tactic/extension_model_converter.cpp      | 94 -------------------
 src/tactic/horn_subsume_model_converter.cpp   |  8 +-
 src/tactic/horn_subsume_model_converter.h     | 13 +--
 src/tactic/model_converter.cpp                | 44 +++++----
 7 files changed, 79 insertions(+), 139 deletions(-)
 delete mode 100644 src/tactic/extension_model_converter.cpp

diff --git a/src/sat/tactic/goal2sat.cpp b/src/sat/tactic/goal2sat.cpp
index f037a0e26..d730ea0ee 100644
--- a/src/sat/tactic/goal2sat.cpp
+++ b/src/sat/tactic/goal2sat.cpp
@@ -881,8 +881,9 @@ struct sat2goal::imp {
 
     // Wrapper for sat::model_converter: converts it into an "AST level" model_converter.
     class sat_model_converter : public model_converter {
-        sat::model_converter        m_mc;
-        expr_ref_vector             m_var2expr;
+        model_converter_ref          m_cached_mc;
+        sat::model_converter         m_mc;
+        expr_ref_vector              m_var2expr;
         generic_model_converter_ref  m_fmc; // filter for eliminating fresh variables introduced in the assertion-set --> sat conversion
         
         sat_model_converter(ast_manager & m):
@@ -1025,6 +1026,9 @@ struct sat2goal::imp {
             if (m_fmc) m_fmc->collect(visitor);
         }
 
+        void operator()(expr_ref& formula) override {
+            NOT_IMPLEMENTED_YET();
+        }
     };
 
     typedef ref<sat_model_converter> sat_model_converter_ref;
@@ -1033,7 +1037,6 @@ struct sat2goal::imp {
     expr_ref_vector         m_lit2expr;
     unsigned long long      m_max_memory;
     bool                    m_learned;
-    unsigned                m_glue;
     
     imp(ast_manager & _m, params_ref const & p):m(_m), m_lit2expr(m) {
         updt_params(p);
@@ -1041,7 +1044,6 @@ struct sat2goal::imp {
 
     void updt_params(params_ref const & p) {
         m_learned        = p.get_bool("learned", false);
-        m_glue           = p.get_uint("glue", UINT_MAX);
         m_max_memory     = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
     }
 
@@ -1131,7 +1133,6 @@ struct sat2goal::imp {
             checkpoint();
             lits.reset();
             sat::clause const & c = *cp;
-            unsigned sz = c.size();
             if (asserted || m_learned || c.glue() <= s.get_config().m_gc_small_lbd) {
                 for (sat::literal l : c) {
                     lits.push_back(lit2expr(mc, l));
@@ -1142,8 +1143,7 @@ struct sat2goal::imp {
     }
 
     sat::ba_solver* get_ba_solver(sat::solver const& s) {
-        sat::extension* ext = s.get_extension();
-        return dynamic_cast<sat::ba_solver*>(ext);
+        return dynamic_cast<sat::ba_solver*>(s.get_extension());
     }
 
     void operator()(sat::solver const & s, atom2bool_var const & map, goal & r, model_converter_ref & mc) {
@@ -1229,7 +1229,6 @@ sat2goal::sat2goal():m_imp(0) {
 void sat2goal::collect_param_descrs(param_descrs & r) {
     insert_max_memory(r);
     r.insert("learned", CPK_BOOL, "(default: false) collect also learned clauses.");
-    r.insert("glue", CPK_UINT, "(default: max-int) collect learned clauses with glue level below parameter.");
 }
 
 struct sat2goal::scoped_set_imp {
diff --git a/src/solver/solver.cpp b/src/solver/solver.cpp
index 8f1287dab..f14467337 100644
--- a/src/solver/solver.cpp
+++ b/src/solver/solver.cpp
@@ -185,21 +185,20 @@ bool solver::is_literal(ast_manager& m, expr* e) {
 
 void solver::assert_expr(expr* f) {
     expr_ref fml(f, get_manager());
-    if (mc0()) {
-        (*mc0())(fml);        
+    model_converter_ref mc = get_model_converter();
+    if (mc) {
+        (*mc)(fml);        
     }
     assert_expr_core(fml);    
 }
 
 void solver::assert_expr(expr* f, expr* t) {
-    // let mc0 be the model converter associated with the solver
-    // that converts models to their "real state".
     ast_manager& m = get_manager();
     expr_ref fml(f, m);
     expr_ref a(t, m);
-
-    if (mc0()) {
-        (*mc0())(fml);        
+    model_converter_ref mc = get_model_converter();
+    if (mc) {
+        (*mc)(fml);        
         // (*mc0())(a);        
     }
     assert_expr_core(fml, a);    
diff --git a/src/tactic/bv/bit_blaster_model_converter.cpp b/src/tactic/bv/bit_blaster_model_converter.cpp
index d8dbb77a4..cdcc486a6 100644
--- a/src/tactic/bv/bit_blaster_model_converter.cpp
+++ b/src/tactic/bv/bit_blaster_model_converter.cpp
@@ -21,6 +21,7 @@ Notes:
 #include "tactic/model_converter.h"
 #include "ast/bv_decl_plugin.h"
 #include "ast/ast_smt2_pp.h"
+#include "ast/ast_util.h"
 
 /**
    If TO_BOOL == true, then bit-vectors of size n were blasted into n-tuples of Booleans.
@@ -171,7 +172,7 @@ struct bit_blaster_model_converter : public model_converter {
         return result;
     }
 
-    virtual void operator()(model_ref & md, unsigned goal_idx) {
+    void operator()(model_ref & md, unsigned goal_idx) override {
         SASSERT(goal_idx == 0);
         model * new_model = alloc(model, m());
         obj_hashtable<func_decl> bits;
@@ -181,11 +182,29 @@ struct bit_blaster_model_converter : public model_converter {
         md = new_model;
     }
 
-    virtual void operator()(model_ref & md) {
+    void operator()(model_ref & md) override {
         operator()(md, 0);
     }
+
+    /**
+       \brief simplisic expansion operator for formulas.
+       It just adds back bit-vector definitions to the formula whether they are used or not.
+
+     */
+    void operator()(expr_ref& fml) override {
+        unsigned sz = m_vars.size();
+        if (sz == 0) return;
+        expr_ref_vector fmls(m());
+        fmls.push_back(fml);
+        for (unsigned i = 0; i < sz; i++) {
+            fmls.push_back(m().mk_eq(m().mk_const(m_vars.get(i)), m_bits.get(i)));
+        }        
+        m_vars.reset();
+        m_bits.reset();
+        fml = mk_and(fmls);
+    }
     
-    virtual void display(std::ostream & out) {
+    void display(std::ostream & out) override {
         unsigned sz = m_vars.size();
         for (unsigned i = 0; i < sz; i++) {
             display_add(out, m(), m_vars.get(i), m_bits.get(i));
@@ -196,7 +215,7 @@ protected:
     bit_blaster_model_converter(ast_manager & m):m_vars(m), m_bits(m) { }
 public:
 
-    virtual model_converter * translate(ast_translation & translator) {
+    model_converter * translate(ast_translation & translator) override {
         bit_blaster_model_converter * res = alloc(bit_blaster_model_converter, translator.to());
         for (func_decl * v : m_vars) 
             res->m_vars.push_back(translator(v));
@@ -207,11 +226,11 @@ public:
 };
 
 model_converter * mk_bit_blaster_model_converter(ast_manager & m, obj_map<func_decl, expr*> const & const2bits) {
-    return alloc(bit_blaster_model_converter<true>, m, const2bits);
+    return const2bits.empty() ? nullptr : alloc(bit_blaster_model_converter<true>, m, const2bits);
 }
 
 model_converter * mk_bv1_blaster_model_converter(ast_manager & m, obj_map<func_decl, expr*> const & const2bits) {
-    return alloc(bit_blaster_model_converter<false>, m, const2bits);
+    return const2bits.empty() ? nullptr : alloc(bit_blaster_model_converter<false>, m, const2bits);
 }
 
 
diff --git a/src/tactic/extension_model_converter.cpp b/src/tactic/extension_model_converter.cpp
deleted file mode 100644
index 0ae4e1323..000000000
--- a/src/tactic/extension_model_converter.cpp
+++ /dev/null
@@ -1,94 +0,0 @@
-/*++
-Copyright (c) 2011 Microsoft Corporation
-
-Module Name:
-
-    extension_model_converter.cpp
-
-Abstract:
-
-Model converter that introduces eliminated variables in a model.
-
-Author:
-
-    Leonardo (leonardo) 2011-10-21
-
-Notes:
-
---*/
-#include "ast/ast_pp.h"
-#include "ast/ast_smt2_pp.h"
-#include "model/model_evaluator.h"
-#include "model/model_v2_pp.h"
-#include "tactic/extension_model_converter.h"
-
-extension_model_converter::~extension_model_converter() {
-}
-
-#ifdef _TRACE
-static void display_decls_info(std::ostream & out, model_ref & md) {
-    ast_manager & m = md->get_manager();
-    unsigned sz = md->get_num_decls();
-    for (unsigned i = 0; i < sz; i++) {
-        func_decl * d = md->get_decl(i);
-        out << d->get_name();
-        out << " (";
-        for (unsigned j = 0; j < d->get_arity(); j++)
-            out << mk_pp(d->get_domain(j), m);
-        out << mk_pp(d->get_range(), m);
-        out << ") ";
-        if (d->get_info())
-            out << *(d->get_info());
-        out << " :id " << d->get_id() << "\n";
-    }
-}
-#endif
-
-void extension_model_converter::operator()(model_ref & md, unsigned goal_idx) {
-    SASSERT(goal_idx == 0);
-    TRACE("extension_mc", model_v2_pp(tout, *md); display_decls_info(tout, md););
-    model_evaluator ev(*(md.get()));
-    ev.set_model_completion(true);
-    ev.set_expand_array_equalities(false);
-    expr_ref val(m());
-    unsigned i = m_vars.size();
-    while (i > 0) {
-        --i;
-        expr * def = m_defs.get(i);
-        ev(def, val);
-        TRACE("extension_mc", tout << m_vars.get(i)->get_name() << " ->\n" << mk_ismt2_pp(def, m()) << "\n==>\n" << mk_ismt2_pp(val, m()) << "\n";);
-        func_decl * f  = m_vars.get(i);
-        unsigned arity = f->get_arity();
-        if (arity == 0) {
-            md->register_decl(f, val);
-        }
-        else {
-            func_interp * new_fi = alloc(func_interp, m(), arity);
-            new_fi->set_else(val);
-            md->register_decl(f, new_fi);
-        }
-    }
-    TRACE("extension_mc", model_v2_pp(tout, *md); display_decls_info(tout, md););
-}
-
-void extension_model_converter::insert(func_decl * v, expr * def) {
-    m_vars.push_back(v);
-    m_defs.push_back(def);    
-}
-
-
-void extension_model_converter::display(std::ostream & out) {
-    for (unsigned i = 0; i < m_vars.size(); i++) {
-        display_add(out, m(), m_vars.get(i), m_defs.get(i));
-    }
-}
-
-model_converter * extension_model_converter::translate(ast_translation & translator) {
-    extension_model_converter * res = alloc(extension_model_converter, translator.to());
-    for (func_decl* v : m_vars)
-        res->m_vars.push_back(translator(v));
-    for (expr* d : m_defs) 
-        res->m_defs.push_back(translator(d));
-    return res;
-}
-
diff --git a/src/tactic/horn_subsume_model_converter.cpp b/src/tactic/horn_subsume_model_converter.cpp
index cb56f9b7b..0d49a769e 100644
--- a/src/tactic/horn_subsume_model_converter.cpp
+++ b/src/tactic/horn_subsume_model_converter.cpp
@@ -170,6 +170,10 @@ void horn_subsume_model_converter::add_default_false_interpretation(expr* e, mod
 }
 
 
+void horn_subsume_model_converter::operator()(expr_ref& fml) {
+    NOT_IMPLEMENTED_YET();
+}
+
 void horn_subsume_model_converter::operator()(model_ref& mr) {
 
     func_decl_ref pred(m);
@@ -190,11 +194,11 @@ void horn_subsume_model_converter::operator()(model_ref& mr) {
         add_default_false_interpretation(body, mr);
         SASSERT(m.is_bool(body));
                 
-        TRACE("mc", tout << "eval: " << h->get_name() << "\n" << mk_pp(body, m) << "\n";);
+        TRACE("mc", tout << "eval: " << h->get_name() << "\n" << body << "\n";);
         expr_ref tmp(body);
         mr->eval(tmp, body);
         
-        TRACE("mc", tout << "to:\n" << mk_pp(body, m) << "\n";);
+        TRACE("mc", tout << "to:\n" << body << "\n";);
                 
         if (arity == 0) {
             expr* e = mr->get_const_interp(h);
diff --git a/src/tactic/horn_subsume_model_converter.h b/src/tactic/horn_subsume_model_converter.h
index 74d5882a5..9b094e575 100644
--- a/src/tactic/horn_subsume_model_converter.h
+++ b/src/tactic/horn_subsume_model_converter.h
@@ -58,9 +58,8 @@ class horn_subsume_model_converter : public model_converter {
 
 public:
 
- horn_subsume_model_converter(ast_manager& m): 
-    m(m), m_funcs(m), m_bodies(m), m_rewrite(m),
-        m_delay_head(m), m_delay_body(m) {}
+    horn_subsume_model_converter(ast_manager& m): 
+        m(m), m_funcs(m), m_bodies(m), m_rewrite(m), m_delay_head(m), m_delay_body(m) {}
 
     bool mk_horn(expr* clause, func_decl_ref& pred, expr_ref& body);
 
@@ -72,13 +71,15 @@ public:
 
     void insert(func_decl* p, expr* body) { m_funcs.push_back(p); m_bodies.push_back(body); }
     
-    virtual void operator()(model_ref& _m);
+    void operator()(model_ref& _m) override;
 
-    virtual model_converter * translate(ast_translation & translator);
+    void operator()(expr_ref& fml) override;
+
+    model_converter * translate(ast_translation & translator) override;
 
     ast_manager& get_manager() { return m; }
 
-    virtual void display(std::ostream & out) {}
+    void display(std::ostream & out) override {}
 };
 
 #endif
diff --git a/src/tactic/model_converter.cpp b/src/tactic/model_converter.cpp
index 01c7a16bb..ab1e2a9bc 100644
--- a/src/tactic/model_converter.cpp
+++ b/src/tactic/model_converter.cpp
@@ -58,28 +58,33 @@ public:
         VERIFY(m_c1 && m_c2);
     }
 
-    virtual void operator()(model_ref & m) {
+    void operator()(model_ref & m) override {
         this->m_c2->operator()(m);
         this->m_c1->operator()(m);
     }
 
-    virtual void operator()(model_ref & m, unsigned goal_idx) {
+    void operator()(expr_ref & fml) override {
+        this->m_c1->operator()(fml);
+        this->m_c2->operator()(fml);
+    }
+    
+    void operator()(model_ref & m, unsigned goal_idx) override {
         this->m_c2->operator()(m, goal_idx);
         this->m_c1->operator()(m, 0);
     }
 
-    virtual void operator()(labels_vec & r, unsigned goal_idx) {
+    void operator()(labels_vec & r, unsigned goal_idx) override {
         this->m_c2->operator()(r, goal_idx);
         this->m_c1->operator()(r, 0);
     }
   
-    virtual char const * get_name() const { return "concat-model-converter"; }
+    char const * get_name() const override { return "concat-model-converter"; }
 
-    virtual model_converter * translate(ast_translation & translator) {
+    model_converter * translate(ast_translation & translator) override {
         return this->translate_core<concat_model_converter>(translator);
     }
 
-    virtual void collect(ast_pp_util& visitor) { 
+    void collect(ast_pp_util& visitor) override { 
         this->m_c1->collect(visitor);
         this->m_c2->collect(visitor);
     }
@@ -99,12 +104,12 @@ public:
         concat_star_converter<model_converter>(mc1, num, mc2s, szs) {
     }
 
-    virtual void operator()(model_ref & m) {
+    void operator()(model_ref & m) override {
         // TODO: delete method after conversion is complete
         UNREACHABLE();
     }
 
-    virtual void operator()(model_ref & m, unsigned goal_idx) {
+    void operator()(model_ref & m, unsigned goal_idx) override {
         unsigned num = this->m_c2s.size();
         for (unsigned i = 0; i < num; i++) {
             if (goal_idx < this->m_szs[i]) {
@@ -122,7 +127,7 @@ public:
         UNREACHABLE();
     }
 
-    virtual void operator()(labels_vec & r, unsigned goal_idx) {
+    void operator()(labels_vec & r, unsigned goal_idx) override {
         unsigned num = this->m_c2s.size();
         for (unsigned i = 0; i < num; i++) {
             if (goal_idx < this->m_szs[i]) {
@@ -140,9 +145,9 @@ public:
         UNREACHABLE();
     }
     
-    virtual char const * get_name() const { return "concat-star-model-converter"; }
+    char const * get_name() const override { return "concat-star-model-converter"; }
 
-    virtual model_converter * translate(ast_translation & translator) {
+    model_converter * translate(ast_translation & translator) override {
         return this->translate_core<concat_star_model_converter>(translator);
     }
 };
@@ -173,22 +178,28 @@ public:
 
     virtual ~model2mc() {}
 
-    virtual void operator()(model_ref & m) {
+    void operator()(model_ref & m) override {
         m = m_model;
     }
 
-    virtual void operator()(model_ref & m, unsigned goal_idx) {
+    void operator()(model_ref & m, unsigned goal_idx) override {
         m = m_model;
     }
 
-    virtual void operator()(labels_vec & r, unsigned goal_idx) {
+    void operator()(labels_vec & r, unsigned goal_idx) {
         r.append(m_labels.size(), m_labels.c_ptr());
     }
 
-    virtual void cancel() {
+    void operator()(expr_ref& fml) override {
+        expr_ref r(m_model->get_manager());
+        m_model->eval(fml, r, false);
+        fml = r;
+    }
+
+    void cancel() override {
     }
     
-    virtual void display(std::ostream & out) {
+    void display(std::ostream & out) override {
         out << "(model->model-converter-wrapper\n";
         model_v2_pp(out, *m_model);
         out << ")\n";
@@ -198,6 +209,7 @@ public:
         model * m = m_model->translate(translator);
         return alloc(model2mc, m);
     }
+
 };
 
 model_converter * model2model_converter(model * m) {