mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	rely on is_sat fallback for failed repair-up, add separate file for WIP on lookahead.
This commit is contained in:
		
							parent
							
								
									13dcfd26dd
								
							
						
					
					
						commit
						d3a6521185
					
				
					 7 changed files with 244 additions and 153 deletions
				
			
		| 
						 | 
				
			
			@ -9,6 +9,7 @@ z3_add_component(ast_sls
 | 
			
		|||
    sls_bv_engine.cpp
 | 
			
		||||
    sls_bv_eval.cpp
 | 
			
		||||
    sls_bv_fixed.cpp
 | 
			
		||||
    sls_bv_lookahead.cpp
 | 
			
		||||
    sls_bv_plugin.cpp
 | 
			
		||||
    sls_bv_terms.cpp
 | 
			
		||||
    sls_bv_valuation.cpp
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -23,6 +23,7 @@ namespace sls {
 | 
			
		|||
        m(ctx.get_manager()),
 | 
			
		||||
        ctx(ctx),
 | 
			
		||||
        terms(terms),
 | 
			
		||||
        m_lookahead(*this),
 | 
			
		||||
        bv(m),
 | 
			
		||||
        m_fix(*this, terms, ctx)
 | 
			
		||||
    {}   
 | 
			
		||||
| 
						 | 
				
			
			@ -121,8 +122,8 @@ namespace sls {
 | 
			
		|||
        SASSERT(m.is_bool(e));
 | 
			
		||||
        SASSERT(e->get_family_id() == bv.get_fid());
 | 
			
		||||
 | 
			
		||||
        bool use_current1 = use_current || (e->get_num_args() > 0 && !m_on_restore.is_marked(e->get_arg(0)));
 | 
			
		||||
        bool use_current2 = use_current || (e->get_num_args() > 1 && !m_on_restore.is_marked(e->get_arg(1)));
 | 
			
		||||
        bool use_current1 = use_current || (e->get_num_args() > 0 && !m_lookahead.on_restore(e->get_arg(0)));
 | 
			
		||||
        bool use_current2 = use_current || (e->get_num_args() > 1 && !m_lookahead.on_restore(e->get_arg(1)));
 | 
			
		||||
        auto ucompare = [&](std::function<bool(int)> const& f) {
 | 
			
		||||
            auto& a = wval(e->get_arg(0)); 
 | 
			
		||||
            auto& b = wval(e->get_arg(1)); 
 | 
			
		||||
| 
						 | 
				
			
			@ -211,8 +212,8 @@ namespace sls {
 | 
			
		|||
            return bval1_bv(e, false);
 | 
			
		||||
        expr* x, * y;
 | 
			
		||||
        if (m.is_eq(e, x, y) && bv.is_bv(x)) {
 | 
			
		||||
            bool use_current1 = !m_on_restore.is_marked(x);
 | 
			
		||||
            bool use_current2 = !m_on_restore.is_marked(y);
 | 
			
		||||
            bool use_current1 = !m_lookahead.on_restore(x);
 | 
			
		||||
            bool use_current2 = !m_lookahead.on_restore(y);
 | 
			
		||||
            return wval(x).tmp_bits(use_current1) == wval(y).tmp_bits(use_current2);
 | 
			
		||||
        }
 | 
			
		||||
        verbose_stream() << mk_bounded_pp(e, m) << "\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -882,35 +883,8 @@ namespace sls {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    bool bv_eval::try_repair_eq_lookahead(app* e) {
 | 
			
		||||
        return false;
 | 
			
		||||
        auto is_true = bval0(e);
 | 
			
		||||
        if (!is_true)
 | 
			
		||||
            return false;
 | 
			
		||||
        auto const& uninterp = terms.uninterp_occurs(e);
 | 
			
		||||
        if (uninterp.empty())
 | 
			
		||||
            return false;
 | 
			
		||||
//        for (auto e : uninterp)
 | 
			
		||||
//            verbose_stream() << mk_bounded_pp(e, m) << " ";
 | 
			
		||||
//        verbose_stream() << "\n";
 | 
			
		||||
        return m_lookahead.try_repair_down(e);
 | 
			
		||||
 | 
			
		||||
        expr* t = uninterp[m_rand() % uninterp.size()];
 | 
			
		||||
 | 
			
		||||
        auto& v = wval(t);
 | 
			
		||||
        if (v.set_random(m_rand)) {
 | 
			
		||||
            //verbose_stream() << "set random " << mk_bounded_pp(t, m) << "\n";
 | 
			
		||||
            ctx.new_value_eh(t);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        for (auto e : uninterp) {
 | 
			
		||||
            auto& v = wval(e);
 | 
			
		||||
            v.get_variant(m_tmp, m_rand);
 | 
			
		||||
            auto d = lookahead(e, m_tmp);
 | 
			
		||||
            //verbose_stream() << mk_bounded_pp(e, m) << " " << d << "\n";
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool bv_eval::try_repair_eq(bool is_true, bvval& a, bvval const& b) {
 | 
			
		||||
| 
						 | 
				
			
			@ -936,13 +910,9 @@ namespace sls {
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
#endif
 | 
			
		||||
            if (m_rand(20) != 0) 
 | 
			
		||||
                if (a.try_set(b.bits()))
 | 
			
		||||
                    return true;
 | 
			
		||||
 | 
			
		||||
            if (m_rand(20) == 0)
 | 
			
		||||
                return a.set_random(m_rand);
 | 
			
		||||
            return false; 
 | 
			
		||||
            if (m_rand(20) != 0 && a.try_set(b.bits()))
 | 
			
		||||
                return true;
 | 
			
		||||
            return a.set_random(m_rand);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            bool try_above = m_rand(2) == 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -1925,7 +1895,20 @@ namespace sls {
 | 
			
		|||
        for (unsigned i = 0; i < a.bw; ++i)
 | 
			
		||||
            m_tmp.set(i, ve.get(i + bw));
 | 
			
		||||
        a.clear_overflow_bits(m_tmp);
 | 
			
		||||
        return a.try_set(m_tmp);
 | 
			
		||||
        bool r = a.try_set(m_tmp);
 | 
			
		||||
        if (!r) {
 | 
			
		||||
            a.add1(m_tmp);
 | 
			
		||||
            r = a.try_set(m_tmp);
 | 
			
		||||
        }
 | 
			
		||||
        if (!r) {
 | 
			
		||||
            r = a.set_repair(random_bool(), m_tmp);
 | 
			
		||||
        }
 | 
			
		||||
        if (!r) {
 | 
			
		||||
            verbose_stream() << "repair concat " << mk_bounded_pp(e, m) << "\n";
 | 
			
		||||
            verbose_stream() << idx << " " << a << "\n" << m_tmp << "\n";
 | 
			
		||||
 | 
			
		||||
        }
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    //
 | 
			
		||||
| 
						 | 
				
			
			@ -1934,7 +1917,7 @@ namespace sls {
 | 
			
		|||
    // set a outside of [hi:lo] to random values with preference to 0 or 1 bits
 | 
			
		||||
    // 
 | 
			
		||||
    bool bv_eval::try_repair_extract(bvect const& e, bvval& a, unsigned lo) {
 | 
			
		||||
        // verbose_stream() << "repair extract a[" << lo << ":" << lo + e.bw - 1 << "] = " << e << "\n";
 | 
			
		||||
        // IF_VERBOSE(4, verbose_stream() << "repair extract a[" << lo << ":" << lo + e.bw - 1 << "] = " << e << "\n");
 | 
			
		||||
        if (false && m_rand(m_config.m_prob_randomize_extract)  <= 100) {
 | 
			
		||||
            a.get_variant(m_tmp, m_rand);
 | 
			
		||||
            if (0 == (m_rand(2))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1953,13 +1936,11 @@ namespace sls {
 | 
			
		|||
        for (unsigned i = 0; i < e.bw; ++i)
 | 
			
		||||
            m_tmp.set(i + lo, e.get(i));
 | 
			
		||||
        m_tmp.set_bw(a.bw);
 | 
			
		||||
        // verbose_stream() << a << " := " << m_tmp << "\n";
 | 
			
		||||
        if (m_rand(20) != 0 && a.try_set(m_tmp))
 | 
			
		||||
        //verbose_stream() << a << " := " << m_tmp << "\n";
 | 
			
		||||
        if (a.try_set(m_tmp))
 | 
			
		||||
            return true;
 | 
			
		||||
        if (m_rand(20) != 0)
 | 
			
		||||
            return false;
 | 
			
		||||
        bool ok = a.set_random(m_rand);
 | 
			
		||||
        // verbose_stream() << "set random " << ok << " " << a << "\n";
 | 
			
		||||
        //verbose_stream() << "set random " << ok << " " << a << "\n";
 | 
			
		||||
        return ok;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1994,6 +1975,7 @@ namespace sls {
 | 
			
		|||
    bool bv_eval::repair_up(expr* e) {
 | 
			
		||||
        if (!is_app(e) || !can_eval1(to_app(e)))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        if (m.is_bool(e)) {
 | 
			
		||||
            bool b = bval1(to_app(e));
 | 
			
		||||
            auto v = ctx.atom2bool_var(e);
 | 
			
		||||
| 
						 | 
				
			
			@ -2006,29 +1988,20 @@ namespace sls {
 | 
			
		|||
 | 
			
		||||
        if (!bv.is_bv(e))
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        auto& v = eval(to_app(e));
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < v.nw; ++i) {
 | 
			
		||||
            if (0 != (v.fixed[i] & (v.bits()[i] ^ v.eval[i]))) {
 | 
			
		||||
                //verbose_stream() << "Fail to set " << mk_bounded_pp(e, m) << " " << i << " " << v.fixed[i] << " " << v.bits()[i] << " " << v.eval[i] << "\n";
 | 
			
		||||
                v.bits().copy_to(v.nw, v.eval);
 | 
			
		||||
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (v.eval == v.bits())
 | 
			
		||||
            return true;
 | 
			
		||||
        //verbose_stream() << "repair up " << mk_bounded_pp(e, m) << " " << v << "\n";
 | 
			
		||||
        if (v.commit_eval()) {
 | 
			
		||||
            ctx.new_value_eh(e);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        //verbose_stream() << "could not repair up " << mk_bounded_pp(e, m) << " " << v << "\n";
 | 
			
		||||
        //for (expr* arg : *to_app(e))
 | 
			
		||||
        //    verbose_stream() << mk_bounded_pp(arg, m) << " " << wval(arg) << "\n";
 | 
			
		||||
        v.bits().copy_to(v.nw, v.eval);
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < v.nw; ++i) 
 | 
			
		||||
            if (0 != (v.fixed[i] & (v.bits()[i] ^ v.eval[i]))) 
 | 
			
		||||
                return false;
 | 
			
		||||
 | 
			
		||||
        if (!v.commit_eval())
 | 
			
		||||
            return false;
 | 
			
		||||
 | 
			
		||||
        ctx.new_value_eh(e);
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sls::bv_valuation& bv_eval::wval(expr* e) const { 
 | 
			
		||||
| 
						 | 
				
			
			@ -2097,73 +2070,5 @@ namespace sls {
 | 
			
		|||
        return out << "?";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    double bv_eval::lookahead(expr* e, bvect const& new_value) {
 | 
			
		||||
        SASSERT(bv.is_bv(e));
 | 
			
		||||
        SASSERT(is_uninterp(e));
 | 
			
		||||
        SASSERT(m_restore.empty());
 | 
			
		||||
 | 
			
		||||
        bool has_tabu = false;
 | 
			
		||||
        double break_count = 0, make_count = 0;
 | 
			
		||||
 | 
			
		||||
        wval(e).eval = new_value;
 | 
			
		||||
        if (!insert_update(e)) {
 | 
			
		||||
            restore_lookahead();
 | 
			
		||||
            return -1000000;
 | 
			
		||||
        }
 | 
			
		||||
        insert_update_stack(e);
 | 
			
		||||
        unsigned max_depth = get_depth(e);
 | 
			
		||||
        for (unsigned depth = max_depth; depth <= max_depth; ++depth) {
 | 
			
		||||
            for (unsigned i = 0; !has_tabu && i < m_update_stack[depth].size(); ++i) {
 | 
			
		||||
                e = m_update_stack[depth][i];
 | 
			
		||||
                if (bv.is_bv(e)) {
 | 
			
		||||
                    auto& v = eval(to_app(e));
 | 
			
		||||
                    if (insert_update(e)) {
 | 
			
		||||
                        for (auto p : ctx.parents(e)) {
 | 
			
		||||
                            insert_update_stack(p);
 | 
			
		||||
                            max_depth = std::max(max_depth, get_depth(p));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                        has_tabu = true;                
 | 
			
		||||
                }
 | 
			
		||||
                else if (m.is_bool(e) && can_eval1(to_app(e))) {
 | 
			
		||||
                    bool is_true = ctx.is_true(e);
 | 
			
		||||
                    bool is_true_new = bval1(to_app(e));
 | 
			
		||||
                    bool is_true_old = bval1_tmp(to_app(e));
 | 
			
		||||
                    // verbose_stream() << "parent " << mk_bounded_pp(e, m) << " " << is_true << " " << is_true_new << " " << is_true_old << "\n";
 | 
			
		||||
                    if (is_true == is_true_new && is_true_new != is_true_old)
 | 
			
		||||
                        ++make_count;
 | 
			
		||||
                    if (is_true == is_true_old && is_true_new != is_true_old)
 | 
			
		||||
                        ++break_count;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            m_update_stack[depth].reset();
 | 
			
		||||
        }
 | 
			
		||||
        restore_lookahead();
 | 
			
		||||
        if (has_tabu)
 | 
			
		||||
            return -10000;
 | 
			
		||||
        return make_count - break_count;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool bv_eval::insert_update(expr* e) {
 | 
			
		||||
        m_restore.push_back(e);
 | 
			
		||||
        m_on_restore.mark(e);
 | 
			
		||||
        auto& v = wval(e);
 | 
			
		||||
        v.save_value();
 | 
			
		||||
        return v.commit_eval();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void bv_eval::insert_update_stack(expr* e) {
 | 
			
		||||
        unsigned depth = get_depth(e);
 | 
			
		||||
        m_update_stack.reserve(depth + 1);
 | 
			
		||||
        if (!m_update_stack[depth].contains(e))
 | 
			
		||||
            m_update_stack[depth].push_back(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void bv_eval::restore_lookahead() {
 | 
			
		||||
        for (auto e : m_restore) 
 | 
			
		||||
            wval(e).restore_value();
 | 
			
		||||
        m_restore.reset();
 | 
			
		||||
        m_on_restore.reset();
 | 
			
		||||
    }
 | 
			
		||||
   
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,8 +20,10 @@ Author:
 | 
			
		|||
#include "ast/sls/sls_bv_valuation.h"
 | 
			
		||||
#include "ast/sls/sls_bv_fixed.h"
 | 
			
		||||
#include "ast/sls/sls_context.h"
 | 
			
		||||
#include "ast/sls/sls_bv_lookahead.h"
 | 
			
		||||
#include "ast/bv_decl_plugin.h"
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
namespace sls {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -31,6 +33,8 @@ namespace sls {
 | 
			
		|||
    using bvect = sls::bvect;
 | 
			
		||||
 | 
			
		||||
    class bv_eval {
 | 
			
		||||
        friend class bv_lookahead;
 | 
			
		||||
 | 
			
		||||
        struct config {
 | 
			
		||||
            unsigned m_prob_randomize_extract = 50;
 | 
			
		||||
        };
 | 
			
		||||
| 
						 | 
				
			
			@ -40,6 +44,7 @@ namespace sls {
 | 
			
		|||
        ast_manager&        m;
 | 
			
		||||
        sls::context&       ctx;
 | 
			
		||||
        sls::bv_terms&      terms;
 | 
			
		||||
        sls::bv_lookahead   m_lookahead;
 | 
			
		||||
        bv_util             bv;
 | 
			
		||||
        sls::bv_fixed       m_fix;
 | 
			
		||||
        mutable mpn_manager mpn;
 | 
			
		||||
| 
						 | 
				
			
			@ -58,13 +63,6 @@ namespace sls {
 | 
			
		|||
 | 
			
		||||
        void init_eval_bv(app* e);
 | 
			
		||||
 | 
			
		||||
        ptr_vector<expr> m_restore;
 | 
			
		||||
        vector<ptr_vector<expr>> m_update_stack;
 | 
			
		||||
        expr_mark m_on_restore;
 | 
			
		||||
        void insert_update_stack(expr* e);
 | 
			
		||||
        bool insert_update(expr* e);
 | 
			
		||||
        double lookahead(expr* e, bvect const& new_value);
 | 
			
		||||
        void restore_lookahead();
 | 
			
		||||
       
 | 
			
		||||
        /**
 | 
			
		||||
        * Register e as a bit-vector. 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										139
									
								
								src/ast/sls/sls_bv_lookahead.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										139
									
								
								src/ast/sls/sls_bv_lookahead.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,139 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2024 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    sls_bv_lookahead.h
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Lookahead solver for BV, modeled after sls_engine/sls_tracker/sls_evaluator.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2024-12-26
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
#include "ast/sls/sls_bv_lookahead.h"
 | 
			
		||||
#include "ast/sls/sls_bv_eval.h"
 | 
			
		||||
#include "ast/sls/sls_bv_terms.h"
 | 
			
		||||
 | 
			
		||||
namespace sls {
 | 
			
		||||
 | 
			
		||||
    bv_lookahead::bv_lookahead(bv_eval& ev) : 
 | 
			
		||||
        bv(ev.bv), 
 | 
			
		||||
        m_ev(ev), 
 | 
			
		||||
        ctx(ev.ctx), 
 | 
			
		||||
        m(ev.m) {}
 | 
			
		||||
 | 
			
		||||
    bool bv_lookahead::try_repair_down(expr* e) {
 | 
			
		||||
        return false;
 | 
			
		||||
        auto is_true = m_ev.bval0(e);
 | 
			
		||||
        if (!is_true)
 | 
			
		||||
            return false;
 | 
			
		||||
        auto const& uninterp = m_ev.terms.uninterp_occurs(e);
 | 
			
		||||
        if (uninterp.empty())
 | 
			
		||||
            return false;
 | 
			
		||||
        //        for (auto e : uninterp)
 | 
			
		||||
        //            verbose_stream() << mk_bounded_pp(e, m) << " ";
 | 
			
		||||
        //        verbose_stream() << "\n";
 | 
			
		||||
 | 
			
		||||
        expr* t = uninterp[m_ev.m_rand() % uninterp.size()];
 | 
			
		||||
 | 
			
		||||
        auto& v = wval(t);
 | 
			
		||||
        if (v.set_random(m_ev.m_rand)) {
 | 
			
		||||
            //verbose_stream() << "set random " << mk_bounded_pp(t, m) << "\n";
 | 
			
		||||
            ctx.new_value_eh(t);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        for (auto e : uninterp) {
 | 
			
		||||
            auto& v = wval(e);
 | 
			
		||||
            v.get_variant(m_ev.m_tmp, m_ev.m_rand);
 | 
			
		||||
            auto d = lookahead(e, m_ev.m_tmp);
 | 
			
		||||
            //verbose_stream() << mk_bounded_pp(e, m) << " " << d << "\n";
 | 
			
		||||
        }
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    double bv_lookahead::lookahead(expr* e, bvect const& new_value) {
 | 
			
		||||
        SASSERT(bv.is_bv(e));
 | 
			
		||||
        SASSERT(is_uninterp(e));
 | 
			
		||||
        SASSERT(m_restore.empty());
 | 
			
		||||
 | 
			
		||||
        bool has_tabu = false;
 | 
			
		||||
        double break_count = 0, make_count = 0;
 | 
			
		||||
 | 
			
		||||
        wval(e).eval = new_value;
 | 
			
		||||
        if (!insert_update(e)) {
 | 
			
		||||
            restore_lookahead();
 | 
			
		||||
            return -1000000;
 | 
			
		||||
        }
 | 
			
		||||
        insert_update_stack(e);
 | 
			
		||||
        unsigned max_depth = get_depth(e);
 | 
			
		||||
        for (unsigned depth = max_depth; depth <= max_depth; ++depth) {
 | 
			
		||||
            for (unsigned i = 0; !has_tabu && i < m_update_stack[depth].size(); ++i) {
 | 
			
		||||
                e = m_update_stack[depth][i];
 | 
			
		||||
                if (bv.is_bv(e)) {
 | 
			
		||||
                    auto& v = m_ev.eval(to_app(e));
 | 
			
		||||
                    if (insert_update(e)) {
 | 
			
		||||
                        for (auto p : ctx.parents(e)) {
 | 
			
		||||
                            insert_update_stack(p);
 | 
			
		||||
                            max_depth = std::max(max_depth, get_depth(p));
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else
 | 
			
		||||
                        has_tabu = true;
 | 
			
		||||
                }
 | 
			
		||||
                else if (m.is_bool(e) && m_ev.can_eval1(to_app(e))) {
 | 
			
		||||
                    bool is_true = ctx.is_true(e);
 | 
			
		||||
                    bool is_true_new = m_ev.bval1(to_app(e));
 | 
			
		||||
                    bool is_true_old = m_ev.bval1_tmp(to_app(e));
 | 
			
		||||
                    // verbose_stream() << "parent " << mk_bounded_pp(e, m) << " " << is_true << " " << is_true_new << " " << is_true_old << "\n";
 | 
			
		||||
                    if (is_true == is_true_new && is_true_new != is_true_old)
 | 
			
		||||
                        ++make_count;
 | 
			
		||||
                    if (is_true == is_true_old && is_true_new != is_true_old)
 | 
			
		||||
                        ++break_count;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            m_update_stack[depth].reset();
 | 
			
		||||
        }
 | 
			
		||||
        restore_lookahead();
 | 
			
		||||
        if (has_tabu)
 | 
			
		||||
            return -10000;
 | 
			
		||||
        return make_count - break_count;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool bv_lookahead::insert_update(expr* e) {
 | 
			
		||||
        m_restore.push_back(e);
 | 
			
		||||
        m_on_restore.mark(e);
 | 
			
		||||
        auto& v = wval(e);
 | 
			
		||||
        v.save_value();
 | 
			
		||||
        return v.commit_eval();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void bv_lookahead::insert_update_stack(expr* e) {
 | 
			
		||||
        unsigned depth = get_depth(e);
 | 
			
		||||
        m_update_stack.reserve(depth + 1);
 | 
			
		||||
        if (!m_update_stack[depth].contains(e))
 | 
			
		||||
            m_update_stack[depth].push_back(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void bv_lookahead::restore_lookahead() {
 | 
			
		||||
        for (auto e : m_restore)
 | 
			
		||||
            wval(e).restore_value();
 | 
			
		||||
        m_restore.reset();
 | 
			
		||||
        m_on_restore.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    sls::bv_valuation& bv_lookahead::wval(expr* e) const {
 | 
			
		||||
        return m_ev.wval(e);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool bv_lookahead::on_restore(expr* e) const {
 | 
			
		||||
        return m_on_restore.is_marked(e);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										53
									
								
								src/ast/sls/sls_bv_lookahead.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										53
									
								
								src/ast/sls/sls_bv_lookahead.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,53 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2024 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    sls_bv_lookahead.h
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Lookahead solver for BV, modeled after sls_engine/sls_tracker/sls_evaluator.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2024-12-26
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#pragma once
 | 
			
		||||
 | 
			
		||||
#include "ast/bv_decl_plugin.h"
 | 
			
		||||
#include "ast/sls/sls_context.h"
 | 
			
		||||
 | 
			
		||||
namespace sls {
 | 
			
		||||
    class bv_eval;
 | 
			
		||||
    class bv_valuation;
 | 
			
		||||
    class bvect;
 | 
			
		||||
 | 
			
		||||
    class bv_lookahead {
 | 
			
		||||
        bv_util bv;
 | 
			
		||||
        bv_eval& m_ev;
 | 
			
		||||
        context& ctx;
 | 
			
		||||
        ast_manager& m;
 | 
			
		||||
 | 
			
		||||
        ptr_vector<expr> m_restore;
 | 
			
		||||
        vector<ptr_vector<expr>> m_update_stack;
 | 
			
		||||
        expr_mark m_on_restore;
 | 
			
		||||
 | 
			
		||||
        bv_valuation& wval(expr* e) const;
 | 
			
		||||
 | 
			
		||||
        void insert_update_stack(expr* e);
 | 
			
		||||
        bool insert_update(expr* e);
 | 
			
		||||
        
 | 
			
		||||
        void restore_lookahead();
 | 
			
		||||
 | 
			
		||||
        double lookahead(expr* e, bvect const& new_value);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        bv_lookahead(bv_eval& ev);
 | 
			
		||||
        bool on_restore(expr* e) const;
 | 
			
		||||
 | 
			
		||||
        bool try_repair_down(expr* e);
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -153,9 +153,10 @@ namespace sls {
 | 
			
		|||
 | 
			
		||||
    void bv_plugin::repair_up(app* e) {
 | 
			
		||||
        if (m_eval.repair_up(e)) {
 | 
			
		||||
            if (!m_eval.eval_is_correct(e)) {
 | 
			
		||||
                verbose_stream() << "Incorrect eval #" << e->get_id() << " " << mk_bounded_pp(e, m) << "\n";
 | 
			
		||||
            }
 | 
			
		||||
            IF_VERBOSE(0,
 | 
			
		||||
                if (!m_eval.eval_is_correct(e))
 | 
			
		||||
                    verbose_stream() << "Incorrect eval #" << e->get_id() << " " << mk_bounded_pp(e, m) << "\n";
 | 
			
		||||
                    );
 | 
			
		||||
            log(e, true, true);
 | 
			
		||||
            SASSERT(m_eval.eval_is_correct(e));
 | 
			
		||||
            if (m.is_bool(e)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -163,14 +164,7 @@ namespace sls {
 | 
			
		|||
                    ctx.flip(ctx.atom2bool_var(e));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else if (bv.is_bv(e)) {
 | 
			
		||||
            log(e, true, false);
 | 
			
		||||
            IF_VERBOSE(5, verbose_stream() << "repair-up "; trace_repair(true, e)); 
 | 
			
		||||
            auto& v = m_eval.wval(e);
 | 
			
		||||
            m_eval.set_random(e);
 | 
			
		||||
            ctx.new_value_eh(e);
 | 
			
		||||
        }
 | 
			
		||||
        else
 | 
			
		||||
        else 
 | 
			
		||||
            log(e, true, false);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -198,6 +198,7 @@ namespace sls {
 | 
			
		|||
                    ++m_stats.m_num_repair_down;
 | 
			
		||||
                    if (p && !p->repair_down(to_app(e)) && !m_repair_up.contains(e->get_id())) {
 | 
			
		||||
                        IF_VERBOSE(3, verbose_stream() << "revert repair: " << mk_bounded_pp(e, m) << "\n");
 | 
			
		||||
                        TRACE("sls", tout << "revert repair: " << mk_bounded_pp(e, m) << "\n");
 | 
			
		||||
                        m_repair_up.insert(e->get_id());
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue