mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	fix sat model converter to work with incrementality
Signed-off-by: Nikolaj Bjorner <nbjorner@microsoft.com>
This commit is contained in:
		
							parent
							
								
									a5b663c52d
								
							
						
					
					
						commit
						c199344bbf
					
				
					 8 changed files with 198 additions and 200 deletions
				
			
		| 
						 | 
				
			
			@ -171,7 +171,7 @@ extern "C" {
 | 
			
		|||
            sat::solver solver(to_solver_ref(s)->get_params(), m.limit());
 | 
			
		||||
            parse_dimacs(is, solver);
 | 
			
		||||
            sat2goal s2g;
 | 
			
		||||
            model_converter_ref mc;
 | 
			
		||||
            ref<sat2goal::mc> mc;
 | 
			
		||||
            atom2bool_var a2b(m);
 | 
			
		||||
            goal g(m);            
 | 
			
		||||
            s2g(solver, a2b, to_solver_ref(s)->get_params(), g, mc);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -324,6 +324,11 @@ namespace sat {
 | 
			
		|||
        m_entries.append(src.m_entries);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void model_converter::flush(model_converter & src) {
 | 
			
		||||
        m_entries.append(src.m_entries);
 | 
			
		||||
        src.m_entries.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void model_converter::collect_vars(bool_var_set & s) const {
 | 
			
		||||
        for (entry const & e : m_entries) s.insert(e.m_var);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -113,8 +113,12 @@ namespace sat {
 | 
			
		|||
        bool check_invariant(unsigned num_vars) const;
 | 
			
		||||
        void display(std::ostream & out) const;
 | 
			
		||||
        bool check_model(model const & m) const;
 | 
			
		||||
 | 
			
		||||
        void copy(model_converter const & src);
 | 
			
		||||
        
 | 
			
		||||
        /*
 | 
			
		||||
          \brief Append entries from src, then remove entries in src.
 | 
			
		||||
        */
 | 
			
		||||
        void flush(model_converter& src);
 | 
			
		||||
        void collect_vars(bool_var_set & s) const;
 | 
			
		||||
        unsigned max_var(unsigned min) const;
 | 
			
		||||
        /*
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -351,6 +351,7 @@ namespace sat {
 | 
			
		|||
        bool model_is_current() const { return m_model_is_current; }
 | 
			
		||||
        literal_vector const& get_core() const { return m_core; }
 | 
			
		||||
        model_converter const & get_model_converter() const { return m_mc; }
 | 
			
		||||
        void flush(model_converter& mc) { mc.flush(m_mc); }
 | 
			
		||||
        void set_model(model const& mdl);
 | 
			
		||||
        char const* get_reason_unknown() const { return m_reason_unknown.c_str(); }
 | 
			
		||||
        bool check_clauses(model const& m) const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ class inc_sat_solver : public solver {
 | 
			
		|||
    proof_converter_ref m_pc;
 | 
			
		||||
    model_converter_ref m_mc;
 | 
			
		||||
    model_converter_ref m_mc0;
 | 
			
		||||
    model_converter_ref m_sat_mc;
 | 
			
		||||
    ref<sat2goal::mc>   m_sat_mc;
 | 
			
		||||
    mutable model_converter_ref m_cached_mc;
 | 
			
		||||
    svector<double>     m_weights;
 | 
			
		||||
    std::string         m_unknown;
 | 
			
		||||
| 
						 | 
				
			
			@ -120,7 +120,7 @@ public:
 | 
			
		|||
        for (expr* f : m_internalized_fmls) result->m_internalized_fmls.push_back(tr(f));
 | 
			
		||||
        if (m_mc) result->m_mc = m_mc->translate(tr);
 | 
			
		||||
        if (m_mc0) result->m_mc0 = m_mc0->translate(tr);
 | 
			
		||||
        //if (m_sat_mc) result->m_sat_mc = m_sat_mc->translate(tr);         MN: commenting this line removes bloat
 | 
			
		||||
        if (m_sat_mc) result->m_sat_mc = dynamic_cast<sat2goal::mc*>(m_sat_mc->translate(tr));
 | 
			
		||||
        // copy m_bb_rewriter?
 | 
			
		||||
        result->m_internalized_converted = m_internalized_converted;
 | 
			
		||||
        return result;
 | 
			
		||||
| 
						 | 
				
			
			@ -531,6 +531,11 @@ private:
 | 
			
		|||
        m_pc = g->pc();
 | 
			
		||||
        m_mc = g->mc();
 | 
			
		||||
        TRACE("sat", g->display_with_dependencies(tout););
 | 
			
		||||
 | 
			
		||||
        // ensure that if goal is already internalized, then import mc from m_solver.
 | 
			
		||||
        if (!m_sat_mc) m_sat_mc = alloc(sat2goal::mc, m);
 | 
			
		||||
        m_sat_mc->flush_smc(m_solver);
 | 
			
		||||
 | 
			
		||||
        m_goal2sat(*g, m_params, m_solver, m_map, dep2asm, is_incremental(), is_lemma);
 | 
			
		||||
        m_goal2sat.get_interpreted_atoms(atoms);
 | 
			
		||||
        if (!atoms.empty()) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -878,173 +878,135 @@ void goal2sat::get_interpreted_atoms(expr_ref_vector& atoms) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
sat2goal::mc::mc(ast_manager& m): m(m), m_var2expr(m) {}
 | 
			
		||||
 | 
			
		||||
void sat2goal::mc::flush_smc(sat::solver& s) {
 | 
			
		||||
    s.flush(m_smc);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sat2goal::mc::flush_gmc() {
 | 
			
		||||
    sat::literal_vector updates;
 | 
			
		||||
    m_smc.expand(updates);
 | 
			
		||||
    m_smc.reset();
 | 
			
		||||
    if (!m_gmc) m_gmc = alloc(generic_model_converter, m);
 | 
			
		||||
    // now gmc owns the model converter
 | 
			
		||||
    sat::literal_vector clause;
 | 
			
		||||
    expr_ref_vector tail(m);
 | 
			
		||||
    expr_ref def(m);
 | 
			
		||||
    for (sat::literal l : updates) {
 | 
			
		||||
        if (l == sat::null_literal) {
 | 
			
		||||
            sat::literal lit0 = clause[0];
 | 
			
		||||
            for (unsigned i = 1; i < clause.size(); ++i) {
 | 
			
		||||
                tail.push_back(lit2expr(~clause[i]));
 | 
			
		||||
            }
 | 
			
		||||
            def = m.mk_or(lit2expr(lit0), mk_and(tail));
 | 
			
		||||
            if (lit0.sign()) {
 | 
			
		||||
                lit0.neg();
 | 
			
		||||
                def = m.mk_not(def);
 | 
			
		||||
            }
 | 
			
		||||
            m_gmc->add(lit2expr(lit0), def);
 | 
			
		||||
            clause.reset();
 | 
			
		||||
            tail.reset();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            clause.push_back(l);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
model_converter* sat2goal::mc::translate(ast_translation& translator) {
 | 
			
		||||
    mc* result = alloc(mc, m);
 | 
			
		||||
    result->m_smc.copy(m_smc);
 | 
			
		||||
    result->m_gmc = m_gmc ? dynamic_cast<generic_model_converter*>(m_gmc->translate(translator)) : nullptr;
 | 
			
		||||
    for (app* e : m_var2expr) {
 | 
			
		||||
        result->m_var2expr.push_back(translator(e));
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sat2goal::mc::collect(ast_pp_util& visitor) {
 | 
			
		||||
    flush_gmc();
 | 
			
		||||
    collect(visitor);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sat2goal::mc::display(std::ostream& out) {
 | 
			
		||||
    flush_gmc();
 | 
			
		||||
    if (m_gmc) m_gmc->display(out);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sat2goal::mc::operator()(model_ref & md) {
 | 
			
		||||
    model_evaluator ev(*md);
 | 
			
		||||
    ev.set_model_completion(false);
 | 
			
		||||
    
 | 
			
		||||
    // create a SAT model using md
 | 
			
		||||
    sat::model sat_md;
 | 
			
		||||
    expr_ref val(m);
 | 
			
		||||
    for (expr * atom : m_var2expr) {
 | 
			
		||||
        if (!atom) {
 | 
			
		||||
            sat_md.push_back(l_undef);
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        ev(atom, val);
 | 
			
		||||
        if (m.is_true(val)) 
 | 
			
		||||
            sat_md.push_back(l_true);
 | 
			
		||||
        else if (m.is_false(val))
 | 
			
		||||
            sat_md.push_back(l_false);
 | 
			
		||||
        else 
 | 
			
		||||
            sat_md.push_back(l_undef);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // apply SAT model converter
 | 
			
		||||
    m_smc(sat_md);
 | 
			
		||||
            
 | 
			
		||||
    // register value of non-auxiliary boolean variables back into md
 | 
			
		||||
    unsigned sz = m_var2expr.size();
 | 
			
		||||
    for (sat::bool_var v = 0; v < sz; v++) {
 | 
			
		||||
        app * atom = m_var2expr.get(v);
 | 
			
		||||
        if (atom && is_uninterp_const(atom)) {
 | 
			
		||||
            func_decl * d = atom->get_decl();
 | 
			
		||||
            lbool new_val = sat_md[v];
 | 
			
		||||
            if (new_val == l_true)
 | 
			
		||||
                md->register_decl(d, m.mk_true());
 | 
			
		||||
            else if (new_val == l_false)
 | 
			
		||||
                md->register_decl(d, m.mk_false());
 | 
			
		||||
        }
 | 
			
		||||
    }    
 | 
			
		||||
    // apply externalized model converter
 | 
			
		||||
    if (m_gmc) (*m_gmc)(md);
 | 
			
		||||
    TRACE("sat_mc", tout << "after sat_mc\n"; model_v2_pp(tout, *md););
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void sat2goal::mc::operator()(expr_ref& fml) {
 | 
			
		||||
    flush_gmc();
 | 
			
		||||
    if (m_gmc) (*m_gmc)(fml);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void sat2goal::mc::insert(sat::bool_var v, app * atom, bool aux) {
 | 
			
		||||
    VERIFY(!m_var2expr.get(v, nullptr));
 | 
			
		||||
    m_var2expr.reserve(v + 1);
 | 
			
		||||
    m_var2expr.set(v, atom);
 | 
			
		||||
    if (aux) {
 | 
			
		||||
        SASSERT(is_uninterp_const(atom));
 | 
			
		||||
        SASSERT(m.is_bool(atom));
 | 
			
		||||
        if (!m_gmc) m_gmc = alloc(generic_model_converter, m);
 | 
			
		||||
        m_gmc->hide(atom->get_decl());
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr_ref sat2goal::mc::lit2expr(sat::literal l) {
 | 
			
		||||
    VERIFY(m_var2expr.get(l.var()));
 | 
			
		||||
    expr_ref result(m_var2expr.get(l.var()), m);
 | 
			
		||||
    if (l.sign()) {
 | 
			
		||||
        result = m.mk_not(result);
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
struct sat2goal::imp {
 | 
			
		||||
 | 
			
		||||
    // Wrapper for sat::model_converter: converts it into an "AST level" model_converter.
 | 
			
		||||
    class sat_model_converter : public model_converter {
 | 
			
		||||
        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
 | 
			
		||||
        generic_model_converter_ref  m_imc; // used to ensure correctness in incremental calls with simplifications that require model conversions
 | 
			
		||||
 | 
			
		||||
        sat_model_converter(ast_manager & m):
 | 
			
		||||
            m_var2expr(m) {
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        void ensure_imc() {
 | 
			
		||||
            if (m_imc) return;
 | 
			
		||||
            m_imc = alloc(generic_model_converter, m());
 | 
			
		||||
            sat::literal_vector updates;
 | 
			
		||||
            m_mc.expand(updates);
 | 
			
		||||
            sat::literal_vector clause;
 | 
			
		||||
            expr_ref_vector tail(m());
 | 
			
		||||
            expr_ref def(m());
 | 
			
		||||
            for (sat::literal l : updates) {
 | 
			
		||||
                if (l == sat::null_literal) {
 | 
			
		||||
                    sat::literal lit0 = clause[0];
 | 
			
		||||
                    for (unsigned i = 1; i < clause.size(); ++i) {
 | 
			
		||||
                        tail.push_back(lit2expr(~clause[i]));
 | 
			
		||||
                    }
 | 
			
		||||
                    def = m().mk_or(lit2expr(lit0), mk_and(tail));
 | 
			
		||||
                    if (lit0.sign()) {
 | 
			
		||||
                        lit0.neg();
 | 
			
		||||
                        def = m().mk_not(def);
 | 
			
		||||
                    }
 | 
			
		||||
                    m_imc->add(lit2expr(lit0), def);
 | 
			
		||||
                    clause.reset();
 | 
			
		||||
                    tail.reset();
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    clause.push_back(l);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        sat_model_converter(ast_manager & m, sat::solver const & s):m_var2expr(m) {
 | 
			
		||||
            m_mc.copy(s.get_model_converter());
 | 
			
		||||
            m_fmc = alloc(generic_model_converter, m);
 | 
			
		||||
            m_imc = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        ast_manager & m() { return m_var2expr.get_manager(); }
 | 
			
		||||
       
 | 
			
		||||
        void init(unsigned num_vars) {
 | 
			
		||||
            m_var2expr.resize(num_vars);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void insert(unsigned v, expr * atom, bool aux) {
 | 
			
		||||
            VERIFY(!m_var2expr.get(v));
 | 
			
		||||
            m_var2expr[v] = atom;
 | 
			
		||||
            if (aux) {
 | 
			
		||||
                SASSERT(is_uninterp_const(atom));
 | 
			
		||||
                SASSERT(m().is_bool(atom));
 | 
			
		||||
                m_fmc->hide(to_app(atom)->get_decl());
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void finish() {
 | 
			
		||||
            sat::literal_vector updates;
 | 
			
		||||
            m_mc.expand(updates);
 | 
			
		||||
            for (sat::literal l : updates) {
 | 
			
		||||
                if (l != sat::null_literal && !m_var2expr.get(l.var())) {
 | 
			
		||||
                    insert(l.var(), m().mk_fresh_const(0, m().mk_bool_sort()), true);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            m_imc = nullptr;
 | 
			
		||||
        }
 | 
			
		||||
                
 | 
			
		||||
        virtual void operator()(model_ref & md) {
 | 
			
		||||
            TRACE("sat_mc", tout << "before sat_mc\n"; model_v2_pp(tout, *md); display(tout););
 | 
			
		||||
            // REMARK: potential problem
 | 
			
		||||
            // model_evaluator can't evaluate quantifiers. Then,
 | 
			
		||||
            // an eliminated variable that depends on a quantified expression can't be recovered.
 | 
			
		||||
            // A similar problem also affects any model_converter that uses elim_var_model_converter.
 | 
			
		||||
            //
 | 
			
		||||
            // Possible solution:
 | 
			
		||||
            //   model_converters reject any variable elimination that depends on a quantified expression.
 | 
			
		||||
            
 | 
			
		||||
            model_evaluator ev(*md);
 | 
			
		||||
            ev.set_model_completion(false);
 | 
			
		||||
            
 | 
			
		||||
            // create a SAT model using md
 | 
			
		||||
            sat::model sat_md;
 | 
			
		||||
            expr_ref val(m());
 | 
			
		||||
            for (expr * atom : m_var2expr) {
 | 
			
		||||
                if (!atom) {
 | 
			
		||||
                    sat_md.push_back(l_undef);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                ev(atom, val);
 | 
			
		||||
                if (m().is_true(val)) 
 | 
			
		||||
                    sat_md.push_back(l_true);
 | 
			
		||||
                else if (m().is_false(val))
 | 
			
		||||
                    sat_md.push_back(l_false);
 | 
			
		||||
                else 
 | 
			
		||||
                    sat_md.push_back(l_undef);
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // apply SAT model converter
 | 
			
		||||
            m_mc(sat_md);
 | 
			
		||||
            
 | 
			
		||||
            // register value of non-auxiliary boolean variables back into md
 | 
			
		||||
            unsigned sz = m_var2expr.size();
 | 
			
		||||
            for (sat::bool_var v = 0; v < sz; v++) {
 | 
			
		||||
                expr * atom = m_var2expr.get(v);
 | 
			
		||||
                if (atom && is_uninterp_const(atom)) {
 | 
			
		||||
                    func_decl * d = to_app(atom)->get_decl();
 | 
			
		||||
                    lbool new_val = sat_md[v];
 | 
			
		||||
                    if (new_val == l_true)
 | 
			
		||||
                        md->register_decl(d, m().mk_true());
 | 
			
		||||
                    else if (new_val == l_false)
 | 
			
		||||
                        md->register_decl(d, m().mk_false());
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            // apply filter model converter
 | 
			
		||||
            (*m_fmc)(md);
 | 
			
		||||
            TRACE("sat_mc", tout << "after sat_mc\n"; model_v2_pp(tout, *md););
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        virtual model_converter * translate(ast_translation & translator) {
 | 
			
		||||
            sat_model_converter * res = alloc(sat_model_converter, translator.to());
 | 
			
		||||
            res->m_mc = m_mc;
 | 
			
		||||
            res->m_fmc = static_cast<generic_model_converter*>(m_fmc->translate(translator));
 | 
			
		||||
            for (expr* e : m_var2expr) 
 | 
			
		||||
                res->m_var2expr.push_back(e ? translator(e) : nullptr);
 | 
			
		||||
            return res;
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        expr_ref lit2expr(sat::literal l) {
 | 
			
		||||
            VERIFY(m_var2expr.get(l.var()));
 | 
			
		||||
            expr_ref result(m_var2expr.get(l.var()), m());
 | 
			
		||||
            if (l.sign()) {
 | 
			
		||||
                result = m().mk_not(result);
 | 
			
		||||
            }
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void display(std::ostream & out) {
 | 
			
		||||
            ensure_imc();
 | 
			
		||||
            m_imc->display(out);
 | 
			
		||||
            m_fmc->display(out);
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        virtual void collect(ast_pp_util& visitor) { 
 | 
			
		||||
            m_env = &visitor.env();
 | 
			
		||||
            for (expr* e : m_var2expr) if (e) visitor.coll.visit(e);
 | 
			
		||||
            if (m_fmc) m_fmc->collect(visitor);
 | 
			
		||||
            ensure_imc();
 | 
			
		||||
            m_imc->collect(visitor);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void operator()(expr_ref& formula) override {
 | 
			
		||||
            ensure_imc();
 | 
			
		||||
            (*m_imc)(formula);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    typedef mc sat_model_converter;
 | 
			
		||||
    typedef ref<sat_model_converter> sat_model_converter_ref;
 | 
			
		||||
 | 
			
		||||
    ast_manager &           m;
 | 
			
		||||
| 
						 | 
				
			
			@ -1073,12 +1035,11 @@ struct sat2goal::imp {
 | 
			
		|||
        m_lit2expr.resize(num_vars * 2);
 | 
			
		||||
        map.mk_inv(m_lit2expr);
 | 
			
		||||
        if (mc) {
 | 
			
		||||
            mc->init(num_vars);
 | 
			
		||||
            for (sat::bool_var v = 0; v < num_vars; v++) {
 | 
			
		||||
                checkpoint();
 | 
			
		||||
                checkpoint();                
 | 
			
		||||
                sat::literal l(v, false);
 | 
			
		||||
                if (m_lit2expr.get(l.index())) {
 | 
			
		||||
                    mc->insert(v, m_lit2expr.get(l.index()), false);
 | 
			
		||||
                    mc->insert(v, to_app(m_lit2expr.get(l.index())), false);
 | 
			
		||||
                    SASSERT(m_lit2expr.get((~l).index()));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1088,9 +1049,12 @@ struct sat2goal::imp {
 | 
			
		|||
    expr * lit2expr(sat_model_converter_ref& mc, sat::literal l) {
 | 
			
		||||
        if (!m_lit2expr.get(l.index())) {
 | 
			
		||||
            SASSERT(m_lit2expr.get((~l).index()) == 0);
 | 
			
		||||
            app * aux = m.mk_fresh_const(0, m.mk_bool_sort());
 | 
			
		||||
            if (mc)
 | 
			
		||||
                mc->insert(l.var(), aux, true);
 | 
			
		||||
            app* aux = mc ? mc->var2expr(l.var()) : nullptr;
 | 
			
		||||
            if (!aux) {
 | 
			
		||||
                aux = m.mk_fresh_const(0, m.mk_bool_sort());
 | 
			
		||||
                if (mc)
 | 
			
		||||
                    mc->insert(l.var(), aux, true);
 | 
			
		||||
            }
 | 
			
		||||
            m_lit2expr.set(l.index(), aux);
 | 
			
		||||
            m_lit2expr.set((~l).index(), m.mk_not(aux));
 | 
			
		||||
        }        
 | 
			
		||||
| 
						 | 
				
			
			@ -1160,27 +1124,26 @@ struct sat2goal::imp {
 | 
			
		|||
        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) {
 | 
			
		||||
    void operator()(sat::solver & s, atom2bool_var const & map, goal & r, ref<mc> & mc) {
 | 
			
		||||
        if (s.inconsistent()) {
 | 
			
		||||
            r.assert_expr(m.mk_false());
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
        ref<sat_model_converter> _mc;
 | 
			
		||||
        if (r.models_enabled()) {
 | 
			
		||||
            _mc = alloc(sat_model_converter, m, s);
 | 
			
		||||
            mc = _mc.get();            
 | 
			
		||||
        if (r.models_enabled() && !mc) {
 | 
			
		||||
            mc = alloc(sat_model_converter, m);
 | 
			
		||||
        }
 | 
			
		||||
        init_lit2expr(s, map, _mc);
 | 
			
		||||
        if (mc) mc->flush_smc(s);
 | 
			
		||||
        init_lit2expr(s, map, mc);
 | 
			
		||||
        // collect units
 | 
			
		||||
        unsigned num_vars = s.num_vars();
 | 
			
		||||
        for (sat::bool_var v = 0; v < num_vars; v++) {
 | 
			
		||||
            checkpoint();
 | 
			
		||||
            switch (s.value(v)) {
 | 
			
		||||
            case l_true:
 | 
			
		||||
                r.assert_expr(lit2expr(_mc, sat::literal(v, false)));
 | 
			
		||||
                r.assert_expr(lit2expr(mc, sat::literal(v, false)));
 | 
			
		||||
                break;
 | 
			
		||||
            case l_false:
 | 
			
		||||
                r.assert_expr(lit2expr(_mc, sat::literal(v, true)));
 | 
			
		||||
                r.assert_expr(lit2expr(mc, sat::literal(v, true)));
 | 
			
		||||
                break;
 | 
			
		||||
            case l_undef:
 | 
			
		||||
                break;
 | 
			
		||||
| 
						 | 
				
			
			@ -1191,28 +1154,27 @@ struct sat2goal::imp {
 | 
			
		|||
        s.collect_bin_clauses(bin_clauses, m_learned);
 | 
			
		||||
        for (sat::solver::bin_clause const& bc : bin_clauses) {
 | 
			
		||||
            checkpoint();
 | 
			
		||||
            r.assert_expr(m.mk_or(lit2expr(_mc, bc.first), lit2expr(_mc, bc.second)));
 | 
			
		||||
            r.assert_expr(m.mk_or(lit2expr(mc, bc.first), lit2expr(mc, bc.second)));
 | 
			
		||||
        }
 | 
			
		||||
        // collect clauses
 | 
			
		||||
        assert_clauses(_mc, s, s.clauses(), r, true);
 | 
			
		||||
        assert_clauses(mc, s, s.clauses(), r, true);
 | 
			
		||||
 | 
			
		||||
        sat::ba_solver* ext = get_ba_solver(s);
 | 
			
		||||
        if (ext) {
 | 
			
		||||
            for (auto* c : ext->constraints()) {
 | 
			
		||||
                switch (c->tag()) {
 | 
			
		||||
                case sat::ba_solver::card_t: 
 | 
			
		||||
                    assert_card(_mc, r, c->to_card());
 | 
			
		||||
                    assert_card(mc, r, c->to_card());
 | 
			
		||||
                    break;
 | 
			
		||||
                case sat::ba_solver::pb_t: 
 | 
			
		||||
                    assert_pb(_mc, r, c->to_pb());
 | 
			
		||||
                    assert_pb(mc, r, c->to_pb());
 | 
			
		||||
                    break;
 | 
			
		||||
                case sat::ba_solver::xor_t: 
 | 
			
		||||
                    assert_xor(_mc, r, c->to_xor());
 | 
			
		||||
                    assert_xor(mc, r, c->to_xor());
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (_mc) _mc->finish();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void add_clause(sat_model_converter_ref& mc, sat::literal_vector const& lits, expr_ref_vector& lemmas) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1255,8 +1217,8 @@ struct sat2goal::scoped_set_imp {
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void sat2goal::operator()(sat::solver const & t, atom2bool_var const & m, params_ref const & p, 
 | 
			
		||||
                          goal & g, model_converter_ref & mc) {
 | 
			
		||||
void sat2goal::operator()(sat::solver & t, atom2bool_var const & m, params_ref const & p, 
 | 
			
		||||
                          goal & g, ref<mc> & mc) {
 | 
			
		||||
    imp proc(g.m(), p);
 | 
			
		||||
    scoped_set_imp set(this, &proc);
 | 
			
		||||
    proc(t, m, g, mc);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,6 +32,7 @@ Notes:
 | 
			
		|||
#include "tactic/goal.h"
 | 
			
		||||
#include "sat/sat_solver.h"
 | 
			
		||||
#include "tactic/model_converter.h"
 | 
			
		||||
#include "tactic/generic_model_converter.h"
 | 
			
		||||
#include "sat/tactic/atom2bool_var.h"
 | 
			
		||||
 | 
			
		||||
class goal2sat {
 | 
			
		||||
| 
						 | 
				
			
			@ -73,8 +74,35 @@ class sat2goal {
 | 
			
		|||
    imp *  m_imp;
 | 
			
		||||
    struct scoped_set_imp;
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    class mc : public model_converter {
 | 
			
		||||
        ast_manager&            m;
 | 
			
		||||
        sat::model_converter    m_smc;
 | 
			
		||||
        generic_model_converter_ref m_gmc;
 | 
			
		||||
        app_ref_vector         m_var2expr;
 | 
			
		||||
 | 
			
		||||
        // flushes from m_smc to m_gmc;
 | 
			
		||||
        void flush_gmc();
 | 
			
		||||
        
 | 
			
		||||
    public:
 | 
			
		||||
        mc(ast_manager& m);
 | 
			
		||||
        virtual ~mc() {}
 | 
			
		||||
        // flush model converter from SAT solver to this structure.
 | 
			
		||||
        void flush_smc(sat::solver& s); 
 | 
			
		||||
        void operator()(model_ref& md) override;
 | 
			
		||||
        void operator()(expr_ref& fml) override; 
 | 
			
		||||
        model_converter* translate(ast_translation& translator) override;
 | 
			
		||||
        void collect(ast_pp_util& visitor) override;
 | 
			
		||||
        void display(std::ostream& out) override;
 | 
			
		||||
        
 | 
			
		||||
        app* var2expr(sat::bool_var v) const { return m_var2expr.get(v, nullptr); }
 | 
			
		||||
        expr_ref lit2expr(sat::literal l);
 | 
			
		||||
        void insert(sat::bool_var v, app * atom, bool aux);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    sat2goal();
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    static void collect_param_descrs(param_descrs & r);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			@ -85,14 +113,7 @@ public:
 | 
			
		|||
       \warning conversion throws a tactic_exception, if it is interrupted (by set_cancel),
 | 
			
		||||
       or memory consumption limit is reached (set with param :max-memory).
 | 
			
		||||
    */
 | 
			
		||||
    void operator()(sat::solver const & t, atom2bool_var const & m, params_ref const & p, goal & s, model_converter_ref & mc);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief extract learned clauses only that are in the domain of m.
 | 
			
		||||
       
 | 
			
		||||
     */
 | 
			
		||||
    void get_learned(sat::solver const& s, atom2bool_var const& m, params_ref const& p, expr_ref_vector& learned);
 | 
			
		||||
    void operator()(sat::solver & t, atom2bool_var const & m, params_ref const & p, goal & s, ref<mc> & mc);
 | 
			
		||||
    
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -108,7 +108,7 @@ class sat_tactic : public tactic {
 | 
			
		|||
                IF_VERBOSE(TACTIC_VERBOSITY_LVL, verbose_stream() << "\"formula constains interpreted atoms, recovering formula from sat solver...\"\n";);
 | 
			
		||||
#endif
 | 
			
		||||
                m_solver.pop_to_base_level();
 | 
			
		||||
                model_converter_ref mc;
 | 
			
		||||
                ref<sat2goal::mc> mc;
 | 
			
		||||
                m_sat2goal(m_solver, map, m_params, *(g.get()), mc);
 | 
			
		||||
                g->add(mc.get());
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue