mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 13:29:11 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/master' into lackr
This commit is contained in:
		
						commit
						c2edf2c5bf
					
				
					 30 changed files with 420 additions and 153 deletions
				
			
		| 
						 | 
				
			
			@ -76,7 +76,6 @@ namespace api {
 | 
			
		|||
        m_sutil(m()),
 | 
			
		||||
        m_last_result(m()),
 | 
			
		||||
        m_ast_trail(m()),
 | 
			
		||||
        m_replay_stack(),
 | 
			
		||||
        m_pmanager(m_limit) {
 | 
			
		||||
 | 
			
		||||
        m_error_code = Z3_OK;
 | 
			
		||||
| 
						 | 
				
			
			@ -100,23 +99,12 @@ namespace api {
 | 
			
		|||
        m_fpa_fid   = m().mk_family_id("fpa");
 | 
			
		||||
        m_seq_fid   = m().mk_family_id("seq");
 | 
			
		||||
        m_dt_plugin = static_cast<datatype_decl_plugin*>(m().get_plugin(m_dt_fid));
 | 
			
		||||
 | 
			
		||||
        if (!m_user_ref_count) {
 | 
			
		||||
            m_replay_stack.push_back(0);
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
        install_tactics(*this);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    context::~context() {
 | 
			
		||||
        m_last_obj = 0;
 | 
			
		||||
        if (!m_user_ref_count) {
 | 
			
		||||
            for (unsigned i = 0; i < m_replay_stack.size(); ++i) {
 | 
			
		||||
                dealloc(m_replay_stack[i]);
 | 
			
		||||
            }
 | 
			
		||||
            m_ast_trail.reset();
 | 
			
		||||
        }
 | 
			
		||||
        reset_parser();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -58,7 +58,7 @@ namespace api {
 | 
			
		|||
        bv_util                    m_bv_util;
 | 
			
		||||
        datalog::dl_decl_util      m_datalog_util;
 | 
			
		||||
        fpa_util                   m_fpa_util;
 | 
			
		||||
	datatype_util              m_dtutil;
 | 
			
		||||
        datatype_util              m_dtutil;
 | 
			
		||||
        seq_util                   m_sutil;
 | 
			
		||||
 | 
			
		||||
        // Support for old solver API
 | 
			
		||||
| 
						 | 
				
			
			@ -67,8 +67,6 @@ namespace api {
 | 
			
		|||
 | 
			
		||||
        ast_ref_vector             m_last_result; //!< used when m_user_ref_count == true
 | 
			
		||||
        ast_ref_vector             m_ast_trail;   //!< used when m_user_ref_count == false
 | 
			
		||||
        unsigned_vector            m_ast_lim;
 | 
			
		||||
        ptr_vector<ast_ref_vector> m_replay_stack;
 | 
			
		||||
 | 
			
		||||
        ref<api::object>           m_last_obj; //!< reference to the last API object returned by the APIs
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +121,7 @@ namespace api {
 | 
			
		|||
        bv_util & bvutil() { return m_bv_util; }
 | 
			
		||||
        datalog::dl_decl_util & datalog_util() { return m_datalog_util; }
 | 
			
		||||
        fpa_util & fpautil() { return m_fpa_util; }
 | 
			
		||||
	datatype_util& dtutil() { return m_dtutil; }
 | 
			
		||||
        datatype_util& dtutil() { return m_dtutil; }
 | 
			
		||||
        seq_util& sutil() { return m_sutil; }
 | 
			
		||||
        family_id get_basic_fid() const { return m_basic_fid; }
 | 
			
		||||
        family_id get_array_fid() const { return m_array_fid; }
 | 
			
		||||
| 
						 | 
				
			
			@ -181,8 +179,6 @@ namespace api {
 | 
			
		|||
        void interrupt();
 | 
			
		||||
 | 
			
		||||
        void invoke_error_handler(Z3_error_code c);
 | 
			
		||||
        
 | 
			
		||||
        static void out_of_memory_handler(void * _ctx);
 | 
			
		||||
 | 
			
		||||
        void check_sorts(ast * n);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9095,6 +9095,10 @@ def _coerce_seq(s, ctx=None):
 | 
			
		|||
    if isinstance(s, str):
 | 
			
		||||
        ctx = _get_ctx(ctx)
 | 
			
		||||
        s = StringVal(s, ctx)
 | 
			
		||||
    if not is_expr(s):
 | 
			
		||||
        raise Z3Exception("Non-expression passed as a sequence")
 | 
			
		||||
    if not is_seq(s):
 | 
			
		||||
        raise Z3Exception("Non-sequence passed as a sequence")
 | 
			
		||||
    return s
 | 
			
		||||
 | 
			
		||||
def _get_ctx2(a, b, ctx=None):
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -923,7 +923,8 @@ void fpa2bv_converter::mk_div(func_decl * f, unsigned num, expr * const * args,
 | 
			
		|||
            m_bv_util.mk_bv_sub(b_exp_ext, b_lz_ext));
 | 
			
		||||
 | 
			
		||||
    expr_ref quotient(m);
 | 
			
		||||
    quotient = m.mk_app(m_bv_util.get_fid(), OP_BUDIV, a_sig_ext, b_sig_ext);
 | 
			
		||||
    // b_sig_ext can't be 0 here, so it's safe to use OP_BUDIV_I
 | 
			
		||||
    quotient = m.mk_app(m_bv_util.get_fid(), OP_BUDIV_I, a_sig_ext, b_sig_ext);
 | 
			
		||||
 | 
			
		||||
    dbg_decouple("fpa2bv_div_quotient", quotient);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,12 +29,27 @@ Notes:
 | 
			
		|||
expr_ref sym_expr::accept(expr* e) {
 | 
			
		||||
    ast_manager& m = m_t.get_manager();
 | 
			
		||||
    expr_ref result(m);
 | 
			
		||||
    if (m_is_pred) {
 | 
			
		||||
    switch (m_ty) {
 | 
			
		||||
    case t_pred: {
 | 
			
		||||
        var_subst subst(m);
 | 
			
		||||
        subst(m_t, 1, &e, result);
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
    case t_char:
 | 
			
		||||
        result = m.mk_eq(e, m_t);
 | 
			
		||||
        break;
 | 
			
		||||
    case t_range: {
 | 
			
		||||
        bv_util bv(m);
 | 
			
		||||
        rational r1, r2, r3;
 | 
			
		||||
        unsigned sz;
 | 
			
		||||
        if (bv.is_numeral(m_t, r1, sz) && bv.is_numeral(e, r2, sz) && bv.is_numeral(m_s, r3, sz)) {
 | 
			
		||||
            result = m.mk_bool_val((r1 <= r2) && (r2 <= r3));            
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            result = m.mk_and(bv.mk_ule(m_t, e), bv.mk_ule(e, m_s));
 | 
			
		||||
        }
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
    return result;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -104,8 +119,7 @@ eautomaton* re2automaton::re2aut(expr* e) {
 | 
			
		|||
            expr_ref v(m.mk_var(0, s), m);
 | 
			
		||||
            expr_ref _start(bv.mk_numeral(start, nb), m);
 | 
			
		||||
            expr_ref _stop(bv.mk_numeral(stop, nb), m);
 | 
			
		||||
            expr_ref cond(m.mk_and(bv.mk_ule(_start, v), bv.mk_ule(v, _stop)), m);
 | 
			
		||||
            a = alloc(eautomaton, sm, sym_expr::mk_pred(cond));
 | 
			
		||||
            a = alloc(eautomaton, sm, sym_expr::mk_range(_start, _stop));
 | 
			
		||||
            return a.detach();
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
| 
						 | 
				
			
			@ -208,7 +222,8 @@ br_status seq_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * con
 | 
			
		|||
    case OP_RE_RANGE:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
    case OP_RE_INTERSECT:
 | 
			
		||||
        return BR_FAILED;    
 | 
			
		||||
        SASSERT(num_args == 2);
 | 
			
		||||
        return mk_re_inter(args[0], args[1], result);
 | 
			
		||||
    case OP_RE_LOOP:
 | 
			
		||||
        return mk_re_loop(num_args, args, result);
 | 
			
		||||
    case OP_RE_EMPTY_SET:
 | 
			
		||||
| 
						 | 
				
			
			@ -359,7 +374,7 @@ br_status seq_rewriter::mk_seq_length(expr* a, expr_ref& result) {
 | 
			
		|||
            es.push_back(m_autil.mk_numeral(rational(len, rational::ui64()), true));
 | 
			
		||||
        }
 | 
			
		||||
        result = m_autil.mk_add(es.size(), es.c_ptr());
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
        return BR_REWRITE2;
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -703,7 +718,8 @@ br_status seq_rewriter::mk_str_stoi(expr* a, expr_ref& result) {
 | 
			
		|||
void seq_rewriter::add_next(u_map<expr*>& next, expr_ref_vector& trail, unsigned idx, expr* cond) {
 | 
			
		||||
    expr* acc;
 | 
			
		||||
    if (!m().is_true(cond) && next.find(idx, acc)) {              
 | 
			
		||||
        cond = m().mk_or(cond, acc);
 | 
			
		||||
        expr* args[2] = { cond, acc };
 | 
			
		||||
        cond = mk_or(m(), 2, args);
 | 
			
		||||
    }
 | 
			
		||||
    trail.push_back(cond);
 | 
			
		||||
    next.insert(idx, cond);   
 | 
			
		||||
| 
						 | 
				
			
			@ -715,8 +731,14 @@ bool seq_rewriter::is_sequence(eautomaton& aut, expr_ref_vector& seq) {
 | 
			
		|||
    unsigned state = aut.init();
 | 
			
		||||
    uint_set visited;
 | 
			
		||||
    eautomaton::moves mvs;
 | 
			
		||||
    aut.get_moves_from(state, mvs, true);
 | 
			
		||||
    while (!aut.is_final_state(state)) {
 | 
			
		||||
    unsigned_vector states;
 | 
			
		||||
    aut.get_epsilon_closure(state, states);
 | 
			
		||||
    bool has_final = false;
 | 
			
		||||
    for (unsigned i = 0; !has_final && i < states.size(); ++i) {
 | 
			
		||||
        has_final = aut.is_final_state(states[i]);
 | 
			
		||||
    }
 | 
			
		||||
    aut.get_moves_from(state, mvs, true);       
 | 
			
		||||
    while (!has_final) {
 | 
			
		||||
        if (mvs.size() != 1) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -735,6 +757,12 @@ bool seq_rewriter::is_sequence(eautomaton& aut, expr_ref_vector& seq) {
 | 
			
		|||
        state = mvs[0].dst();
 | 
			
		||||
        mvs.reset();
 | 
			
		||||
        aut.get_moves_from(state, mvs, true);
 | 
			
		||||
        states.reset();
 | 
			
		||||
        has_final = false;
 | 
			
		||||
        aut.get_epsilon_closure(state, states);
 | 
			
		||||
        for (unsigned i = 0; !has_final && i < states.size(); ++i) {
 | 
			
		||||
            has_final = aut.is_final_state(states[i]);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return mvs.empty();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -773,6 +801,14 @@ bool seq_rewriter::is_sequence(expr* e, expr_ref_vector& seq) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
 | 
			
		||||
    if (m_util.re.is_empty(b)) {
 | 
			
		||||
        result = m().mk_false();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_full(b)) {
 | 
			
		||||
        result = m().mk_true();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    scoped_ptr<eautomaton> aut;
 | 
			
		||||
    expr_ref_vector seq(m());
 | 
			
		||||
    if (!(aut = m_re2aut(b))) {
 | 
			
		||||
| 
						 | 
				
			
			@ -817,7 +853,7 @@ br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
            aut->get_moves_from(state, mvs, false);
 | 
			
		||||
            for (unsigned j = 0; j < mvs.size(); ++j) {
 | 
			
		||||
                eautomaton::move const& mv = mvs[j];
 | 
			
		||||
				SASSERT(mv.t());
 | 
			
		||||
                SASSERT(mv.t());
 | 
			
		||||
                if (mv.t()->is_char() && m().is_value(mv.t()->get_char()) && m().is_value(ch)) {
 | 
			
		||||
                    if (mv.t()->get_char() == ch) {
 | 
			
		||||
                        add_next(next, trail, mv.dst(), acc);
 | 
			
		||||
| 
						 | 
				
			
			@ -828,7 +864,11 @@ br_status seq_rewriter::mk_str_in_regexp(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    cond = mv.t()->accept(ch);
 | 
			
		||||
                    if (!m().is_true(acc)) cond = m().mk_and(acc, cond);
 | 
			
		||||
                    if (m().is_false(cond)) {
 | 
			
		||||
                        continue;
 | 
			
		||||
                    }
 | 
			
		||||
                    expr* args[2] = { cond, acc };
 | 
			
		||||
                    cond = mk_and(m(), 2, args);
 | 
			
		||||
                    add_next(next, trail, mv.dst(), cond);
 | 
			
		||||
                }
 | 
			
		||||
            }                
 | 
			
		||||
| 
						 | 
				
			
			@ -856,18 +896,18 @@ br_status seq_rewriter::mk_str_to_regexp(expr* a, expr_ref& result) {
 | 
			
		|||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
br_status seq_rewriter::mk_re_concat(expr* a, expr* b, expr_ref& result) {
 | 
			
		||||
	if (m_util.re.is_full(a) && m_util.re.is_full(b)) {
 | 
			
		||||
		result = a;
 | 
			
		||||
		return BR_DONE;
 | 
			
		||||
	}
 | 
			
		||||
	if (m_util.re.is_empty(a)) {
 | 
			
		||||
		result = a;
 | 
			
		||||
		return BR_DONE;
 | 
			
		||||
	}
 | 
			
		||||
	if (m_util.re.is_empty(b)) {
 | 
			
		||||
		result = b;
 | 
			
		||||
		return BR_DONE;
 | 
			
		||||
	}
 | 
			
		||||
    if (m_util.re.is_full(a) && m_util.re.is_full(b)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_empty(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_empty(b)) {
 | 
			
		||||
        result = b;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (is_epsilon(a)) {
 | 
			
		||||
        result = b;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
| 
						 | 
				
			
			@ -916,6 +956,38 @@ br_status seq_rewriter::mk_re_union(expr* a, expr* b, expr_ref& result) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   (emp n r) = emp
 | 
			
		||||
   (r n emp) = emp
 | 
			
		||||
   (all n r) = r
 | 
			
		||||
   (r n all) = r
 | 
			
		||||
   (r n r) = r
 | 
			
		||||
 */
 | 
			
		||||
br_status seq_rewriter::mk_re_inter(expr* a, expr* b, expr_ref& result) {
 | 
			
		||||
    if (a == b) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_empty(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_empty(b)) {
 | 
			
		||||
        result = b;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_full(a)) {
 | 
			
		||||
        result = b;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_full(b)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
br_status seq_rewriter::mk_re_loop(unsigned num_args, expr* const* args, expr_ref& result) {
 | 
			
		||||
    rational n1, n2;
 | 
			
		||||
    switch (num_args) {
 | 
			
		||||
| 
						 | 
				
			
			@ -945,13 +1017,26 @@ br_status seq_rewriter::mk_re_loop(unsigned num_args, expr* const* args, expr_re
 | 
			
		|||
  (a* + b)* = (a + b)*
 | 
			
		||||
  (a + b*)* = (a + b)*
 | 
			
		||||
  (a*b*)*   = (a + b)*
 | 
			
		||||
   a+* = a*
 | 
			
		||||
   emp* = ""
 | 
			
		||||
   all* = all   
 | 
			
		||||
*/
 | 
			
		||||
br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
 | 
			
		||||
    expr* b, *c, *b1, *c1;
 | 
			
		||||
    if (m_util.re.is_star(a) || m_util.re.is_empty(a) || m_util.re.is_full(a)) {
 | 
			
		||||
    if (m_util.re.is_star(a) || m_util.re.is_full(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_empty(a)) {
 | 
			
		||||
        sort* seq_sort = 0;
 | 
			
		||||
        VERIFY(m_util.is_re(a, seq_sort));
 | 
			
		||||
        result = m_util.re.mk_to_re(m_util.str.mk_empty(seq_sort));
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_plus(a, b)) {
 | 
			
		||||
        result = m_util.re.mk_star(b);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_union(a, b, c)) {
 | 
			
		||||
        if (m_util.re.is_star(b, b1)) {
 | 
			
		||||
            result = m_util.re.mk_star(m_util.re.mk_union(b1, c));
 | 
			
		||||
| 
						 | 
				
			
			@ -961,6 +1046,14 @@ br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
 | 
			
		|||
            result = m_util.re.mk_star(m_util.re.mk_union(b, c1));
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_epsilon(b)) {
 | 
			
		||||
            result = m_util.re.mk_star(c);
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        }
 | 
			
		||||
        if (is_epsilon(c)) {
 | 
			
		||||
            result = m_util.re.mk_star(b);
 | 
			
		||||
            return BR_REWRITE2;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_concat(a, b, c) &&
 | 
			
		||||
        m_util.re.is_star(b, b1) && m_util.re.is_star(c, c1)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -972,9 +1065,34 @@ br_status seq_rewriter::mk_re_star(expr* a, expr_ref& result) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
   emp+ = emp
 | 
			
		||||
   all+ = all
 | 
			
		||||
   a*+ = a*
 | 
			
		||||
   a++ = a+
 | 
			
		||||
   a+ = aa*
 | 
			
		||||
*/
 | 
			
		||||
br_status seq_rewriter::mk_re_plus(expr* a, expr_ref& result) {
 | 
			
		||||
    if (m_util.re.is_empty(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_full(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (is_epsilon(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_plus(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    if (m_util.re.is_star(a)) {
 | 
			
		||||
        result = a;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
//  result = m_util.re.mk_concat(a, m_util.re.mk_star(a));
 | 
			
		||||
//  return BR_REWRITE2;
 | 
			
		||||
| 
						 | 
				
			
			@ -1052,14 +1170,13 @@ bool seq_rewriter::reduce_eq(expr_ref_vector& ls, expr_ref_vector& rs, expr_ref_
 | 
			
		|||
                rs.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
                expr_ref s2(m_util.str.mk_string(s.extract(0, s.length()-2)), m());
 | 
			
		||||
                expr_ref s2(m_util.str.mk_string(s.extract(0, s.length()-1)), m());
 | 
			
		||||
                rs[rs.size()-1] = s2;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        TRACE("seq", tout << "change back\n";);
 | 
			
		||||
        change = true;
 | 
			
		||||
        lchange = true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,20 +27,27 @@ Notes:
 | 
			
		|||
#include"automaton.h"
 | 
			
		||||
 | 
			
		||||
class sym_expr {
 | 
			
		||||
    bool     m_is_pred;
 | 
			
		||||
    enum ty {
 | 
			
		||||
        t_char,
 | 
			
		||||
        t_pred,
 | 
			
		||||
        t_range
 | 
			
		||||
    };
 | 
			
		||||
    ty       m_ty;
 | 
			
		||||
    expr_ref m_t;
 | 
			
		||||
    expr_ref m_s;
 | 
			
		||||
    unsigned m_ref;
 | 
			
		||||
    sym_expr(bool is_pred, expr_ref& t) : m_is_pred(is_pred), m_t(t), m_ref(0) {}
 | 
			
		||||
    sym_expr(ty ty, expr_ref& t, expr_ref& s) : m_ty(ty), m_t(t), m_s(s), m_ref(0) {}
 | 
			
		||||
public:
 | 
			
		||||
    expr_ref accept(expr* e);
 | 
			
		||||
    static sym_expr* mk_char(expr_ref& t) { return alloc(sym_expr, false, t); }
 | 
			
		||||
    static sym_expr* mk_char(ast_manager& m, expr* t) { expr_ref tr(t, m); return alloc(sym_expr, false, tr); }
 | 
			
		||||
    static sym_expr* mk_pred(expr_ref& t) { return alloc(sym_expr, true, t); }
 | 
			
		||||
    static sym_expr* mk_char(expr_ref& t) { return alloc(sym_expr, t_char, t, t); }
 | 
			
		||||
    static sym_expr* mk_char(ast_manager& m, expr* t) { expr_ref tr(t, m); return mk_char(tr); }
 | 
			
		||||
    static sym_expr* mk_pred(expr_ref& t) { return alloc(sym_expr, t_pred, t, t); }
 | 
			
		||||
    static sym_expr* mk_range(expr_ref& lo, expr_ref& hi) { return alloc(sym_expr, t_range, lo, hi); }
 | 
			
		||||
    void inc_ref() { ++m_ref;  }
 | 
			
		||||
    void dec_ref() { --m_ref; if (m_ref == 0) dealloc(this); }
 | 
			
		||||
    std::ostream& display(std::ostream& out) const;
 | 
			
		||||
    bool is_char() const { return !m_is_pred; }
 | 
			
		||||
    bool is_pred() const { return m_is_pred; }
 | 
			
		||||
    bool is_char() const { return m_ty == t_char; }
 | 
			
		||||
    bool is_pred() const { return !is_char(); }
 | 
			
		||||
    expr* get_char() const { SASSERT(is_char()); return m_t; }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -88,6 +95,7 @@ class seq_rewriter {
 | 
			
		|||
    br_status mk_str_to_regexp(expr* a, expr_ref& result);
 | 
			
		||||
    br_status mk_re_concat(expr* a, expr* b, expr_ref& result);
 | 
			
		||||
    br_status mk_re_union(expr* a, expr* b, expr_ref& result);
 | 
			
		||||
    br_status mk_re_inter(expr* a, expr* b, expr_ref& result);
 | 
			
		||||
    br_status mk_re_star(expr* a, expr_ref& result);
 | 
			
		||||
    br_status mk_re_plus(expr* a, expr_ref& result);
 | 
			
		||||
    br_status mk_re_opt(expr* a, expr_ref& result);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -612,9 +612,8 @@ func_decl * seq_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters,
 | 
			
		|||
                               func_decl_info(m_family_id, OP_STRING_CONST, num_parameters, parameters));
 | 
			
		||||
        
 | 
			
		||||
    case OP_RE_UNION:
 | 
			
		||||
        return mk_assoc_fun(k, arity, domain, range, k, k);
 | 
			
		||||
 | 
			
		||||
    case OP_RE_CONCAT:  
 | 
			
		||||
    case OP_RE_INTERSECT:  
 | 
			
		||||
        return mk_assoc_fun(k, arity, domain, range, k, k);
 | 
			
		||||
 | 
			
		||||
    case OP_SEQ_CONCAT: 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -268,6 +268,7 @@ public:
 | 
			
		|||
        MATCH_TERNARY(is_extract);
 | 
			
		||||
        MATCH_BINARY(is_contains);
 | 
			
		||||
        MATCH_BINARY(is_at);
 | 
			
		||||
        MATCH_BINARY(is_index);
 | 
			
		||||
        MATCH_TERNARY(is_index);
 | 
			
		||||
        MATCH_TERNARY(is_replace);
 | 
			
		||||
        MATCH_BINARY(is_prefix);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,8 @@ Notes:
 | 
			
		|||
#include"model_smt2_pp.h"
 | 
			
		||||
#include"model_v2_pp.h"
 | 
			
		||||
#include"model_params.hpp"
 | 
			
		||||
#include"th_rewriter.h"
 | 
			
		||||
#include"tactic_exception.h"
 | 
			
		||||
 | 
			
		||||
func_decls::func_decls(ast_manager & m, func_decl * f):
 | 
			
		||||
    m_decls(TAG(func_decl*, f, 0)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1462,7 +1464,8 @@ void cmd_context::check_sat(unsigned num_assumptions, expr * const * assumptions
 | 
			
		|||
            throw ex;
 | 
			
		||||
        }
 | 
			
		||||
        catch (z3_exception & ex) {
 | 
			
		||||
            throw cmd_exception(ex.msg());
 | 
			
		||||
            m_solver->set_reason_unknown(ex.msg());
 | 
			
		||||
            r = l_undef;
 | 
			
		||||
        }
 | 
			
		||||
        m_solver->set_status(r);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1624,6 +1627,7 @@ void cmd_context::validate_model() {
 | 
			
		|||
                TRACE("model_validate", tout << "checking\n" << mk_ismt2_pp(a, m()) << "\nresult:\n" << mk_ismt2_pp(r, m()) << "\n";);
 | 
			
		||||
                if (m().is_true(r))
 | 
			
		||||
                    continue;
 | 
			
		||||
 | 
			
		||||
                // The evaluator for array expressions is not complete
 | 
			
		||||
                // If r contains as_array/store/map/const expressions, then we do not generate the error.
 | 
			
		||||
                // TODO: improve evaluator for model expressions.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -105,6 +105,8 @@ public:
 | 
			
		|||
    // create an automaton from initial state, final states, and moves
 | 
			
		||||
    automaton(M& m, unsigned init, unsigned_vector const& final, moves const& mvs): m(m) {
 | 
			
		||||
        m_init = init;
 | 
			
		||||
        m_delta.push_back(moves());
 | 
			
		||||
        m_delta_inv.push_back(moves());
 | 
			
		||||
        for (unsigned i = 0; i < final.size(); ++i) {
 | 
			
		||||
            add_to_final_states(final[i]);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -331,6 +333,7 @@ public:
 | 
			
		|||
    //  Src - ET -> dst - e -> dst1 => Src - ET -> dst1  if out_degree(dst) = 1, 
 | 
			
		||||
    //
 | 
			
		||||
    void compress() {
 | 
			
		||||
        SASSERT(!m_delta.empty());
 | 
			
		||||
        for (unsigned i = 0; i < m_delta.size(); ++i) {
 | 
			
		||||
            for (unsigned j = 0; j < m_delta[i].size(); ++j) {
 | 
			
		||||
                move const& mv = m_delta[i][j];
 | 
			
		||||
| 
						 | 
				
			
			@ -419,6 +422,7 @@ public:
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        SASSERT(!m_delta.empty());
 | 
			
		||||
        while (true) {
 | 
			
		||||
            SASSERT(!m_delta.empty());
 | 
			
		||||
            unsigned src = m_delta.size() - 1;            
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -24,6 +24,7 @@ Revision History:
 | 
			
		|||
#include"arith_rewriter.h"
 | 
			
		||||
#include"bv_rewriter.h"
 | 
			
		||||
#include"pb_rewriter.h"
 | 
			
		||||
#include"seq_rewriter.h"
 | 
			
		||||
#include"datatype_rewriter.h"
 | 
			
		||||
#include"array_rewriter.h"
 | 
			
		||||
#include"fpa_rewriter.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -39,6 +40,7 @@ struct evaluator_cfg : public default_rewriter_cfg {
 | 
			
		|||
    datatype_rewriter               m_dt_rw;
 | 
			
		||||
    pb_rewriter                     m_pb_rw;
 | 
			
		||||
    fpa_rewriter                    m_f_rw;
 | 
			
		||||
    seq_rewriter                    m_seq_rw;
 | 
			
		||||
    unsigned long long              m_max_memory;
 | 
			
		||||
    unsigned                        m_max_steps;
 | 
			
		||||
    bool                            m_model_completion;
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +57,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
 | 
			
		|||
        m_ar_rw(m, p),
 | 
			
		||||
        m_dt_rw(m),
 | 
			
		||||
        m_pb_rw(m),
 | 
			
		||||
        m_f_rw(m) {
 | 
			
		||||
        m_f_rw(m),
 | 
			
		||||
        m_seq_rw(m) {
 | 
			
		||||
        m_b_rw.set_flat(false);
 | 
			
		||||
        m_a_rw.set_flat(false);
 | 
			
		||||
        m_bv_rw.set_flat(false);
 | 
			
		||||
| 
						 | 
				
			
			@ -139,6 +142,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
 | 
			
		|||
                    st = m_dt_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                else if (s_fid == m_f_rw.get_fid())
 | 
			
		||||
                    st = m_f_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                else if (s_fid == m_seq_rw.get_fid())
 | 
			
		||||
                    st = m_seq_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                if (st != BR_FAILED)
 | 
			
		||||
                    return st;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -157,6 +162,8 @@ struct evaluator_cfg : public default_rewriter_cfg {
 | 
			
		|||
            st = m_pb_rw.mk_app_core(f, num, args, result);
 | 
			
		||||
        else if (fid == m_f_rw.get_fid())
 | 
			
		||||
            st = m_f_rw.mk_app_core(f, num, args, result);
 | 
			
		||||
        else if (fid == m_seq_rw.get_fid())
 | 
			
		||||
            st = m_seq_rw.mk_app_core(f, num, args, result);
 | 
			
		||||
        else if (evaluate(f, num, args, result)) {
 | 
			
		||||
            TRACE("model_evaluator", tout << "reduce_app " << f->get_name() << "\n";
 | 
			
		||||
                  for (unsigned i = 0; i < num; i++) tout << mk_ismt2_pp(args[i], m()) << "\n";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -132,7 +132,8 @@ namespace opt {
 | 
			
		|||
        m_objective_refs(m),
 | 
			
		||||
        m_enable_sat(false),
 | 
			
		||||
        m_is_clausal(false),
 | 
			
		||||
        m_pp_neat(false)
 | 
			
		||||
        m_pp_neat(false),
 | 
			
		||||
        m_unknown("unknown")
 | 
			
		||||
    {
 | 
			
		||||
        params_ref p;
 | 
			
		||||
        p.set_bool("model", true);
 | 
			
		||||
| 
						 | 
				
			
			@ -487,7 +488,7 @@ namespace opt {
 | 
			
		|||
        if (m_solver.get()) {
 | 
			
		||||
            return m_solver->reason_unknown();
 | 
			
		||||
        }
 | 
			
		||||
        return std::string("unknown"); 
 | 
			
		||||
        return m_unknown;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void context::display_bounds(std::ostream& out, bounds_t const& b) const {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -163,6 +163,7 @@ namespace opt {
 | 
			
		|||
        symbol                       m_maxsat_engine;
 | 
			
		||||
        symbol                       m_logic;
 | 
			
		||||
        svector<symbol>              m_labels;
 | 
			
		||||
        std::string                  m_unknown;
 | 
			
		||||
    public:
 | 
			
		||||
        context(ast_manager& m);
 | 
			
		||||
        virtual ~context();
 | 
			
		||||
| 
						 | 
				
			
			@ -184,6 +185,7 @@ namespace opt {
 | 
			
		|||
        virtual void get_labels(svector<symbol> & r);
 | 
			
		||||
        virtual void get_unsat_core(ptr_vector<expr> & r) {}
 | 
			
		||||
        virtual std::string reason_unknown() const;
 | 
			
		||||
        virtual void set_reason_unknown(char const* msg) { m_unknown = msg; }
 | 
			
		||||
 | 
			
		||||
        virtual void display_assignment(std::ostream& out);
 | 
			
		||||
        virtual bool is_pareto() { return m_pareto.get() != 0; }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -290,6 +290,10 @@ namespace opt {
 | 
			
		|||
    std::string opt_solver::reason_unknown() const {
 | 
			
		||||
        return m_context.last_failure_as_string();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void opt_solver::set_reason_unknown(char const* msg) {
 | 
			
		||||
        m_context.set_reason_unknown(msg);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void opt_solver::get_labels(svector<symbol> & r) {
 | 
			
		||||
        r.reset();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -99,6 +99,7 @@ namespace opt {
 | 
			
		|||
        virtual void get_model(model_ref & _m);        
 | 
			
		||||
        virtual proof * get_proof();
 | 
			
		||||
        virtual std::string reason_unknown() const;
 | 
			
		||||
        virtual void set_reason_unknown(char const* msg);
 | 
			
		||||
        virtual void get_labels(svector<symbol> & r);
 | 
			
		||||
        virtual void set_progress_callback(progress_callback * callback);
 | 
			
		||||
        virtual unsigned get_num_assertions() const;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -432,8 +432,10 @@ namespace smt2 {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        void unknown_sort(symbol id) {
 | 
			
		||||
            std::string msg = "unknown sort '";
 | 
			
		||||
        void unknown_sort(symbol id, char const* context = "") {
 | 
			
		||||
            std::string msg = context;
 | 
			
		||||
            if (context[0]) msg += ": ";
 | 
			
		||||
            msg += "unknown sort '";
 | 
			
		||||
            msg += id.str() + "'";
 | 
			
		||||
            throw parser_exception(msg.c_str());
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -528,12 +530,12 @@ namespace smt2 {
 | 
			
		|||
            SASSERT(sexpr_stack().size() == stack_pos + 1);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        sort * parse_sort_name() {
 | 
			
		||||
        sort * parse_sort_name(char const* context = "") {
 | 
			
		||||
            SASSERT(curr_is_identifier());
 | 
			
		||||
            symbol id = curr_id();
 | 
			
		||||
            psort_decl * d = m_ctx.find_psort_decl(id);
 | 
			
		||||
            if (d == 0)
 | 
			
		||||
                unknown_sort(id);
 | 
			
		||||
                unknown_sort(id, context);
 | 
			
		||||
            if (!d->has_var_params() && d->get_num_params() != 0)
 | 
			
		||||
                throw parser_exception("sort constructor expects parameters");
 | 
			
		||||
            sort * r = d->instantiate(pm());
 | 
			
		||||
| 
						 | 
				
			
			@ -689,23 +691,24 @@ namespace smt2 {
 | 
			
		|||
            next();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void parse_sort() {
 | 
			
		||||
        void parse_sort(char const* context) {
 | 
			
		||||
            unsigned stack_pos  = sort_stack().size();
 | 
			
		||||
            unsigned num_frames = 0;
 | 
			
		||||
            do {
 | 
			
		||||
                if (curr_is_identifier()) {
 | 
			
		||||
                    sort_stack().push_back(parse_sort_name());
 | 
			
		||||
                    sort_stack().push_back(parse_sort_name(context));
 | 
			
		||||
                }
 | 
			
		||||
                else if (curr_is_rparen()) {
 | 
			
		||||
                    if (num_frames == 0)
 | 
			
		||||
                        throw parser_exception("invalid sort, unexpected ')'");
 | 
			
		||||
                    if (num_frames == 0) {
 | 
			
		||||
                        throw parser_exception(std::string(context) + " invalid sort, unexpected ')'");
 | 
			
		||||
                    }
 | 
			
		||||
                    pop_sort_app_frame();
 | 
			
		||||
                    num_frames--;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    check_lparen_next("invalid sort, symbol, '_' or '(' expected");
 | 
			
		||||
                    if (!curr_is_identifier()) 
 | 
			
		||||
                        throw parser_exception("invalid sort, symbol or '_' expected"); 
 | 
			
		||||
                        throw parser_exception(std::string(context) + " invalid sort, symbol or '_' expected"); 
 | 
			
		||||
                    if (curr_id_is_underscore()) {
 | 
			
		||||
                        sort_stack().push_back(parse_indexed_sort());
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -723,7 +726,7 @@ namespace smt2 {
 | 
			
		|||
            unsigned sz = 0;            
 | 
			
		||||
            check_lparen_next(context);
 | 
			
		||||
            while (!curr_is_rparen()) {
 | 
			
		||||
                parse_sort();
 | 
			
		||||
                parse_sort(context);
 | 
			
		||||
                sz++;
 | 
			
		||||
            }
 | 
			
		||||
            next();
 | 
			
		||||
| 
						 | 
				
			
			@ -1151,7 +1154,7 @@ namespace smt2 {
 | 
			
		|||
                symbol_stack().push_back(curr_id());
 | 
			
		||||
                TRACE("parse_sorted_vars", tout << "push_back curr_id(): " << curr_id() << "\n";);
 | 
			
		||||
                next();
 | 
			
		||||
                parse_sort();
 | 
			
		||||
                parse_sort("invalid sorted variables");
 | 
			
		||||
                check_rparen_next("invalid sorted variable, ')' expected");
 | 
			
		||||
                num++;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1243,7 +1246,7 @@ namespace smt2 {
 | 
			
		|||
                has_as   = true;
 | 
			
		||||
                next();
 | 
			
		||||
                symbol r = parse_indexed_identifier();
 | 
			
		||||
                parse_sort();
 | 
			
		||||
                parse_sort("Invalid qualified identifier");
 | 
			
		||||
                check_rparen_next("invalid qualified identifier, ')' expected");
 | 
			
		||||
                return r;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -1848,7 +1851,7 @@ namespace smt2 {
 | 
			
		|||
            unsigned sort_spos = sort_stack().size();
 | 
			
		||||
            unsigned expr_spos = expr_stack().size();
 | 
			
		||||
            unsigned num_vars  = parse_sorted_vars();
 | 
			
		||||
            parse_sort();
 | 
			
		||||
            parse_sort("Invalid function definition");
 | 
			
		||||
            parse_expr();
 | 
			
		||||
            if (m().get_sort(expr_stack().back()) != sort_stack().back())
 | 
			
		||||
                throw parser_exception("invalid function/constant definition, sort mismatch");
 | 
			
		||||
| 
						 | 
				
			
			@ -1936,7 +1939,7 @@ namespace smt2 {
 | 
			
		|||
            unsigned expr_spos = expr_stack().size();
 | 
			
		||||
            unsigned num_vars  = parse_sorted_vars();
 | 
			
		||||
            SASSERT(num_vars == m_num_bindings);
 | 
			
		||||
            parse_sort();
 | 
			
		||||
            parse_sort("Invalid recursive function definition");
 | 
			
		||||
            f = m().mk_func_decl(id, num_vars, sort_stack().c_ptr() + sort_spos, sort_stack().back());
 | 
			
		||||
            bindings.append(num_vars, expr_stack().c_ptr() + expr_spos);
 | 
			
		||||
            ids.append(num_vars, symbol_stack().c_ptr() + sym_spos);
 | 
			
		||||
| 
						 | 
				
			
			@ -1999,7 +2002,7 @@ namespace smt2 {
 | 
			
		|||
            check_identifier("invalid constant definition, symbol expected");
 | 
			
		||||
            symbol id = curr_id();
 | 
			
		||||
            next();
 | 
			
		||||
            parse_sort();
 | 
			
		||||
            parse_sort("Invalid constant definition");
 | 
			
		||||
            parse_expr();
 | 
			
		||||
            if (m().get_sort(expr_stack().back()) != sort_stack().back())
 | 
			
		||||
                throw parser_exception("invalid constant definition, sort mismatch");
 | 
			
		||||
| 
						 | 
				
			
			@ -2020,7 +2023,7 @@ namespace smt2 {
 | 
			
		|||
            next();
 | 
			
		||||
            unsigned spos = sort_stack().size();
 | 
			
		||||
            unsigned num_params = parse_sorts("Parsing function declaration. Expecting sort list '('");
 | 
			
		||||
            parse_sort();
 | 
			
		||||
            parse_sort("Invalid function declaration");
 | 
			
		||||
            func_decl_ref f(m());
 | 
			
		||||
            f = m().mk_func_decl(id, num_params, sort_stack().c_ptr() + spos, sort_stack().back());
 | 
			
		||||
            sort_stack().shrink(spos);
 | 
			
		||||
| 
						 | 
				
			
			@ -2037,7 +2040,7 @@ namespace smt2 {
 | 
			
		|||
            check_identifier("invalid constant declaration, symbol expected");
 | 
			
		||||
            symbol id = curr_id();
 | 
			
		||||
            next();
 | 
			
		||||
            parse_sort();
 | 
			
		||||
            parse_sort("Invalid constant declaration");
 | 
			
		||||
            SASSERT(!sort_stack().empty());
 | 
			
		||||
            func_decl_ref c(m());
 | 
			
		||||
            c = m().mk_const_decl(id, sort_stack().back());
 | 
			
		||||
| 
						 | 
				
			
			@ -2300,9 +2303,9 @@ namespace smt2 {
 | 
			
		|||
                    next();
 | 
			
		||||
                }
 | 
			
		||||
                unsigned spos = sort_stack().size();
 | 
			
		||||
                parse_sorts("Parsing function name. Expecting sort list startig with '(' to disambiguate function name");
 | 
			
		||||
                parse_sorts("Invalid function name. Expecting sort list startig with '(' to disambiguate function name");
 | 
			
		||||
                unsigned domain_size = sort_stack().size() - spos;
 | 
			
		||||
                parse_sort();
 | 
			
		||||
                parse_sort("Invalid function name");
 | 
			
		||||
                func_decl * d = m_ctx.find_func_decl(id, indices.size(), indices.c_ptr(), domain_size, sort_stack().c_ptr() + spos, sort_stack().back());
 | 
			
		||||
                sort_stack().shrink(spos);
 | 
			
		||||
                check_rparen_next("invalid function declaration reference, ')' expected");
 | 
			
		||||
| 
						 | 
				
			
			@ -2375,7 +2378,7 @@ namespace smt2 {
 | 
			
		|||
                break;
 | 
			
		||||
            }
 | 
			
		||||
            case CPK_SORT:
 | 
			
		||||
                parse_sort();
 | 
			
		||||
                parse_sort("invalid command argument, sort expected");
 | 
			
		||||
                m_curr_cmd->set_next_arg(m_ctx, sort_stack().back());
 | 
			
		||||
                return;
 | 
			
		||||
            case CPK_SORT_LIST: {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ namespace smt2 {
 | 
			
		|||
        }
 | 
			
		||||
        m_spos++;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    void scanner::read_comment() {
 | 
			
		||||
        SASSERT(curr() == ';');
 | 
			
		||||
        next();
 | 
			
		||||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ namespace smt2 {
 | 
			
		|||
            next();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    scanner::token scanner::read_quoted_symbol() {
 | 
			
		||||
        SASSERT(curr() == '|');
 | 
			
		||||
        bool escape = false;
 | 
			
		||||
| 
						 | 
				
			
			@ -105,7 +105,7 @@ namespace smt2 {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    scanner::token scanner::read_symbol() {
 | 
			
		||||
        SASSERT(m_normalized[static_cast<unsigned>(curr())] == 'a' || curr() == ':' || curr() == '-');
 | 
			
		||||
        m_string.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -113,14 +113,14 @@ namespace smt2 {
 | 
			
		|||
        next();
 | 
			
		||||
        return read_symbol_core();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    scanner::token scanner::read_number() {
 | 
			
		||||
        SASSERT('0' <= curr() && curr() <= '9');
 | 
			
		||||
        rational q(1);
 | 
			
		||||
        m_number = rational(curr() - '0');
 | 
			
		||||
        next();
 | 
			
		||||
        bool is_float = false;
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        while (true) {
 | 
			
		||||
            char c = curr();
 | 
			
		||||
            if ('0' <= c && c <= '9') {
 | 
			
		||||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ namespace smt2 {
 | 
			
		|||
                break;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (is_float) 
 | 
			
		||||
        if (is_float)
 | 
			
		||||
            m_number /= q;
 | 
			
		||||
        TRACE("scanner", tout << "new number: " << m_number << "\n";);
 | 
			
		||||
        return is_float ? FLOAT_TOKEN : INT_TOKEN;
 | 
			
		||||
| 
						 | 
				
			
			@ -160,14 +160,14 @@ namespace smt2 {
 | 
			
		|||
            return read_symbol_core();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    scanner::token scanner::read_string() {
 | 
			
		||||
        SASSERT(curr() == '\"');
 | 
			
		||||
        next();
 | 
			
		||||
        m_string.reset();
 | 
			
		||||
        while (true) {
 | 
			
		||||
            char c = curr();
 | 
			
		||||
            if (c == EOF) 
 | 
			
		||||
            if (c == EOF)
 | 
			
		||||
                throw scanner_exception("unexpected end of string", m_line, m_spos);
 | 
			
		||||
            if (c == '\n') {
 | 
			
		||||
                new_line();
 | 
			
		||||
| 
						 | 
				
			
			@ -183,7 +183,7 @@ namespace smt2 {
 | 
			
		|||
            next();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    scanner::token scanner::read_bv_literal() {
 | 
			
		||||
        SASSERT(curr() == '#');
 | 
			
		||||
        next();
 | 
			
		||||
| 
						 | 
				
			
			@ -200,7 +200,7 @@ namespace smt2 {
 | 
			
		|||
                }
 | 
			
		||||
                else if ('a' <= c && c <= 'f') {
 | 
			
		||||
                    m_number *= rational(16);
 | 
			
		||||
                    m_number += rational(10 + (c - 'a')); 
 | 
			
		||||
                    m_number += rational(10 + (c - 'a'));
 | 
			
		||||
                }
 | 
			
		||||
                else if ('A' <= c && c <= 'F') {
 | 
			
		||||
                    m_number *= rational(16);
 | 
			
		||||
| 
						 | 
				
			
			@ -236,9 +236,9 @@ namespace smt2 {
 | 
			
		|||
            throw scanner_exception("invalid bit-vector literal, expecting 'x' or 'b'", m_line, m_spos);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    scanner::scanner(cmd_context & ctx, std::istream& stream, bool interactive):
 | 
			
		||||
        m_interactive(interactive), 
 | 
			
		||||
        m_interactive(interactive),
 | 
			
		||||
        m_spos(0),
 | 
			
		||||
        m_curr(0), // avoid Valgrind warning
 | 
			
		||||
        m_line(1),
 | 
			
		||||
| 
						 | 
				
			
			@ -248,7 +248,7 @@ namespace smt2 {
 | 
			
		|||
        m_bend(0),
 | 
			
		||||
        m_stream(stream),
 | 
			
		||||
        m_cache_input(false) {
 | 
			
		||||
        
 | 
			
		||||
 | 
			
		||||
        m_smtlib2_compliant = ctx.params().m_smtlib2_compliant;
 | 
			
		||||
 | 
			
		||||
        for (int i = 0; i < 256; ++i) {
 | 
			
		||||
| 
						 | 
				
			
			@ -287,7 +287,7 @@ namespace smt2 {
 | 
			
		|||
        m_normalized[static_cast<int>('/')] = 'a';
 | 
			
		||||
        next();
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
    scanner::token scanner::scan() {
 | 
			
		||||
        while (true) {
 | 
			
		||||
            signed char c = curr();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -60,6 +60,8 @@ class inc_sat_solver : public solver {
 | 
			
		|||
    model_converter_ref m_mc2;   
 | 
			
		||||
    expr_dependency_ref m_dep_core;
 | 
			
		||||
    svector<double>     m_weights;
 | 
			
		||||
    std::string         m_unknown;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    typedef obj_map<expr, sat::literal> dep2asm_t;
 | 
			
		||||
public:
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +75,8 @@ public:
 | 
			
		|||
        m_map(m),
 | 
			
		||||
        m_bb_rewriter(m, p),
 | 
			
		||||
        m_num_scopes(0), 
 | 
			
		||||
        m_dep_core(m) {
 | 
			
		||||
        m_dep_core(m),
 | 
			
		||||
        m_unknown("no reason given") {
 | 
			
		||||
        m_params.set_bool("elim_vars", false);
 | 
			
		||||
        m_solver.updt_params(m_params);
 | 
			
		||||
        params_ref simp2_p = p;
 | 
			
		||||
| 
						 | 
				
			
			@ -243,8 +246,12 @@ public:
 | 
			
		|||
        UNREACHABLE();
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    virtual std::string reason_unknown() const {
 | 
			
		||||
        return "no reason given";
 | 
			
		||||
        return m_unknown;
 | 
			
		||||
    }
 | 
			
		||||
    virtual void set_reason_unknown(char const* msg) {
 | 
			
		||||
        m_unknown = msg;
 | 
			
		||||
    }
 | 
			
		||||
    virtual void get_labels(svector<symbol> & r) {
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -72,6 +72,7 @@ namespace smt {
 | 
			
		|||
        m_not_l(null_literal),
 | 
			
		||||
        m_conflict_resolution(mk_conflict_resolution(m, *this, m_dyn_ack_manager, p, m_assigned_literals, m_watches)),
 | 
			
		||||
        m_unsat_proof(m),
 | 
			
		||||
        m_unknown("unknown"),
 | 
			
		||||
        m_unsat_core(m),
 | 
			
		||||
#ifdef Z3DEBUG
 | 
			
		||||
        m_trail_enabled(true),
 | 
			
		||||
| 
						 | 
				
			
			@ -4110,8 +4111,7 @@ namespace smt {
 | 
			
		|||
              m_fingerprints.display(tout); 
 | 
			
		||||
              );
 | 
			
		||||
        failure fl = get_last_search_failure();
 | 
			
		||||
        if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS) {
 | 
			
		||||
            // don't generate model.
 | 
			
		||||
        if (fl == MEMOUT || fl == CANCELED || fl == TIMEOUT || fl == NUM_CONFLICTS) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4126,7 +4126,6 @@ namespace smt {
 | 
			
		|||
            if (m_fparams.m_model_compact)
 | 
			
		||||
                m_proto_model->compress();
 | 
			
		||||
            TRACE("mbqi_bug", tout << "after cleanup:\n"; model_pp(tout, *m_proto_model););
 | 
			
		||||
            //SASSERT(validate_model());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,6 +71,7 @@ namespace smt {
 | 
			
		|||
 | 
			
		||||
        std::ostream& display_last_failure(std::ostream& out) const;
 | 
			
		||||
        std::string last_failure_as_string() const;
 | 
			
		||||
        void set_reason_unknown(char const* msg) { m_unknown = msg; }
 | 
			
		||||
        void set_progress_callback(progress_callback *callback);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -197,6 +198,7 @@ namespace smt {
 | 
			
		|||
        // -----------------------------------
 | 
			
		||||
        proto_model_ref            m_proto_model;
 | 
			
		||||
        model_ref                  m_model;
 | 
			
		||||
        std::string                m_unknown;
 | 
			
		||||
        void                       mk_proto_model(lbool r);
 | 
			
		||||
        struct scoped_mk_model;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ namespace smt {
 | 
			
		|||
    std::string context::last_failure_as_string() const {
 | 
			
		||||
        std::string r;
 | 
			
		||||
        switch(m_last_search_failure) {
 | 
			
		||||
        case OK: r = "ok"; break;
 | 
			
		||||
        case OK: r = m_unknown; break;
 | 
			
		||||
        case TIMEOUT: r = "timeout"; break;
 | 
			
		||||
        case MEMOUT: r = "memout"; break;
 | 
			
		||||
        case CANCELED: r = "canceled"; break;
 | 
			
		||||
| 
						 | 
				
			
			@ -79,7 +79,7 @@ namespace smt {
 | 
			
		|||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case QUANTIFIERS: r = "(incomplete quantifiers)"; break;
 | 
			
		||||
        case UNKNOWN: r = "incomplete"; break;
 | 
			
		||||
        case UNKNOWN: r = m_unknown; break;
 | 
			
		||||
        }
 | 
			
		||||
        return r;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -238,7 +238,7 @@ namespace smt {
 | 
			
		|||
                    out << "equivalence classes:\n";
 | 
			
		||||
                    first = false;
 | 
			
		||||
                }
 | 
			
		||||
                out << "#" << n->get_id() << " -> #" << r->get_id() << "\n";
 | 
			
		||||
                out << "#" << n->get_id() << " -> #" << r->get_id() << ": ";
 | 
			
		||||
                out << mk_pp(n, m_manager) << " -> " << mk_pp(r, m_manager) << "\n";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,6 +123,10 @@ namespace smt {
 | 
			
		|||
            return m_kernel.last_failure_as_string();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void set_reason_unknown(char const* msg) {
 | 
			
		||||
            m_kernel.set_reason_unknown(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void get_assignments(expr_ref_vector & result) {
 | 
			
		||||
            m_kernel.get_assignments(result);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -284,6 +288,10 @@ namespace smt {
 | 
			
		|||
        return m_imp->last_failure_as_string();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void kernel::set_reason_unknown(char const* msg) {
 | 
			
		||||
        m_imp->set_reason_unknown(msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void kernel::get_assignments(expr_ref_vector & result) {
 | 
			
		||||
        m_imp->get_assignments(result);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -155,6 +155,12 @@ namespace smt {
 | 
			
		|||
        */
 | 
			
		||||
        std::string last_failure_as_string() const;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Set the reason for unknown.
 | 
			
		||||
        */
 | 
			
		||||
        void set_reason_unknown(char const* msg);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Return the set of formulas assigned by the kernel.
 | 
			
		||||
        */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,6 +95,10 @@ namespace smt {
 | 
			
		|||
            return m_context.last_failure_as_string();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void set_reason_unknown(char const* msg) {
 | 
			
		||||
            m_context.set_reason_unknown(msg);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        virtual void get_labels(svector<symbol> & r) {
 | 
			
		||||
            buffer<symbol> tmp;
 | 
			
		||||
            m_context.get_relevant_labels(0, tmp);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -221,6 +221,11 @@ final_check_status theory_seq::final_check_eh() {
 | 
			
		|||
        TRACE("seq", tout << ">>propagate_automata\n";);
 | 
			
		||||
        return FC_CONTINUE;
 | 
			
		||||
    }
 | 
			
		||||
    if (!check_extensionality()) {
 | 
			
		||||
        ++m_stats.m_extensionality;
 | 
			
		||||
        TRACE("seq", tout << ">>extensionality\n";);
 | 
			
		||||
        return FC_CONTINUE;
 | 
			
		||||
    }
 | 
			
		||||
    if (is_solved()) {
 | 
			
		||||
        TRACE("seq", tout << ">>is_solved\n";);
 | 
			
		||||
        return FC_DONE;
 | 
			
		||||
| 
						 | 
				
			
			@ -239,9 +244,9 @@ bool theory_seq::branch_variable() {
 | 
			
		|||
        unsigned k = (i + start) % sz;
 | 
			
		||||
        eq const& e = m_eqs[k];
 | 
			
		||||
        unsigned id = e.id();
 | 
			
		||||
        TRACE("seq", tout << e.ls() << " = " << e.rs() << "\n";);
 | 
			
		||||
 | 
			
		||||
        s = find_branch_start(2*id);
 | 
			
		||||
        TRACE("seq", tout << s << " " << 2*id << ": " << e.ls() << " = " << e.rs() << "\n";);
 | 
			
		||||
        bool found = find_branch_candidate(s, e.dep(), e.ls(), e.rs());
 | 
			
		||||
        insert_branch_start(2*id, s);
 | 
			
		||||
        if (found) {
 | 
			
		||||
| 
						 | 
				
			
			@ -292,11 +297,14 @@ bool theory_seq::find_branch_candidate(unsigned& start, dependency* dep, expr_re
 | 
			
		|||
 | 
			
		||||
    expr_ref v0(m);
 | 
			
		||||
    v0 = m_util.str.mk_empty(m.get_sort(l));
 | 
			
		||||
    if (can_be_equal(ls.size() - 1, ls.c_ptr() + 1, rs.size(), rs.c_ptr()) && l_false != assume_equality(l, v0)) {
 | 
			
		||||
        TRACE("seq", tout << mk_pp(l, m) << " " << v0 << "\n";);
 | 
			
		||||
        return true;
 | 
			
		||||
    literal_vector lits;
 | 
			
		||||
    if (can_be_equal(ls.size() - 1, ls.c_ptr() + 1, rs.size(), rs.c_ptr())) {
 | 
			
		||||
        if (l_false != assume_equality(l, v0)) {
 | 
			
		||||
            TRACE("seq", tout << mk_pp(l, m) << " " << v0 << "\n";);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
        lits.push_back(~mk_eq_empty(l));
 | 
			
		||||
    }
 | 
			
		||||
//    start = 0;
 | 
			
		||||
    for (; start < rs.size(); ++start) {
 | 
			
		||||
        unsigned j = start;
 | 
			
		||||
        SASSERT(!m_util.str.is_concat(rs[j]));
 | 
			
		||||
| 
						 | 
				
			
			@ -320,11 +328,11 @@ bool theory_seq::find_branch_candidate(unsigned& start, dependency* dep, expr_re
 | 
			
		|||
        all_units &= m_util.str.is_unit(rs[j]);
 | 
			
		||||
    }
 | 
			
		||||
    if (all_units) {
 | 
			
		||||
        literal_vector lits;
 | 
			
		||||
        lits.push_back(~mk_eq_empty(l));
 | 
			
		||||
        for (unsigned i = 0; i < rs.size(); ++i) {
 | 
			
		||||
            v0 = mk_concat(i + 1, rs.c_ptr());
 | 
			
		||||
            lits.push_back(~mk_eq(l, v0, false));
 | 
			
		||||
            if (can_be_equal(ls.size() - 1, ls.c_ptr() + 1, rs.size() - i - 1, rs.c_ptr() + i + 1)) {
 | 
			
		||||
                v0 = mk_concat(i + 1, rs.c_ptr());
 | 
			
		||||
                lits.push_back(~mk_eq(l, v0, false));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        set_conflict(dep, lits);
 | 
			
		||||
        TRACE("seq", tout << mk_pp(l, m) << " " << v0 << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			@ -501,11 +509,23 @@ expr_ref theory_seq::mk_nth(expr* s, expr* idx) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
expr_ref theory_seq::mk_last(expr* s) {
 | 
			
		||||
    zstring str;
 | 
			
		||||
    if (m_util.str.is_string(s, str) && str.length() > 0) {
 | 
			
		||||
        return expr_ref(m_util.str.mk_char(str, str.length()-1), m);
 | 
			
		||||
    }
 | 
			
		||||
    sort* char_sort = 0;
 | 
			
		||||
    VERIFY(m_util.is_seq(m.get_sort(s), char_sort));
 | 
			
		||||
    return mk_skolem(m_seq_last, s, 0, 0, char_sort);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr_ref theory_seq::mk_first(expr* s) {
 | 
			
		||||
    zstring str;
 | 
			
		||||
    if (m_util.str.is_string(s, str) && str.length() > 0) {
 | 
			
		||||
        return expr_ref(m_util.str.mk_string(str.extract(0, str.length()-1)), m);
 | 
			
		||||
    }
 | 
			
		||||
    return mk_skolem(m_seq_first, s);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
void theory_seq::mk_decompose(expr* e, expr_ref& head, expr_ref& tail) {
 | 
			
		||||
    expr* e1, *e2;
 | 
			
		||||
| 
						 | 
				
			
			@ -541,6 +561,44 @@ void theory_seq::mk_decompose(expr* e, expr_ref& head, expr_ref& tail) {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
   \brief Check extensionality (for sequences).
 | 
			
		||||
 */
 | 
			
		||||
bool theory_seq::check_extensionality() {
 | 
			
		||||
    context& ctx = get_context();
 | 
			
		||||
    unsigned sz = get_num_vars();
 | 
			
		||||
    unsigned_vector seqs;
 | 
			
		||||
    for (unsigned v = 0; v < sz; ++v) {
 | 
			
		||||
        enode* n = get_enode(v);
 | 
			
		||||
        expr* o1 = n->get_owner();
 | 
			
		||||
        if (n != n->get_root()) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        if (!seqs.empty() && ctx.is_relevant(n) && m_util.is_seq(o1) && ctx.is_shared(n)) {
 | 
			
		||||
            dependency* dep = 0;
 | 
			
		||||
            expr_ref e1 = canonize(o1, dep);
 | 
			
		||||
            for (unsigned i = 0; i < seqs.size(); ++i) {
 | 
			
		||||
                enode* n2 = get_enode(seqs[i]);
 | 
			
		||||
                expr* o2 = n2->get_owner();
 | 
			
		||||
                if (m_exclude.contains(o1, o2)) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                expr_ref e2 = canonize(n2->get_owner(), dep);
 | 
			
		||||
                m_lhs.reset(); m_rhs.reset();
 | 
			
		||||
                bool change = false;
 | 
			
		||||
                if (!m_seq_rewrite.reduce_eq(o1, o2, m_lhs, m_rhs, change)) {
 | 
			
		||||
                    m_exclude.update(o1, o2);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                TRACE("seq", tout << mk_pp(o1, m) << " = " << mk_pp(o2, m) << "\n";);
 | 
			
		||||
                ctx.assume_eq(n, n2);                
 | 
			
		||||
                return false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        seqs.push_back(v);
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
   - Eqs = 0
 | 
			
		||||
| 
						 | 
				
			
			@ -634,15 +692,12 @@ void theory_seq::enforce_length_coherence(enode* n1, enode* n2) {
 | 
			
		|||
    expr* o1 = n1->get_owner();
 | 
			
		||||
    expr* o2 = n2->get_owner();
 | 
			
		||||
    if (m_util.str.is_concat(o1) && m_util.str.is_concat(o2)) {
 | 
			
		||||
        //std::cout << "concats:\n" << mk_pp(o1,m) << "\n" << mk_pp(o2,m) << "\n";
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    if (has_length(o1) && !has_length(o2)) {
 | 
			
		||||
        //std::cout << "enforce length: " << mk_pp(o1,m) << " -> " << mk_pp(o2,m) << "\n";
 | 
			
		||||
        enforce_length(n2);
 | 
			
		||||
    }
 | 
			
		||||
    else if (has_length(o2) && !has_length(o1)) {
 | 
			
		||||
        //std::cout << "enforce length: " << mk_pp(o2,m) << " -> " << mk_pp(o1,m) << "\n";
 | 
			
		||||
        enforce_length(n1);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -778,7 +833,6 @@ bool theory_seq::solve_eqs(unsigned i) {
 | 
			
		|||
    bool change = false;
 | 
			
		||||
    for (; !ctx.inconsistent() && i < m_eqs.size(); ++i) {
 | 
			
		||||
        eq const& e = m_eqs[i];
 | 
			
		||||
        TRACE("seq", tout << i << "\n";);
 | 
			
		||||
        if (solve_eq(e.ls(), e.rs(), e.dep())) {
 | 
			
		||||
            if (i + 1 != m_eqs.size()) {
 | 
			
		||||
                eq e1 = m_eqs[m_eqs.size()-1];
 | 
			
		||||
| 
						 | 
				
			
			@ -835,7 +889,6 @@ bool theory_seq::propagate_max_length(expr* l, expr* r, dependency* deps) {
 | 
			
		|||
    }
 | 
			
		||||
    rational hi;
 | 
			
		||||
    if (is_tail(l, s, idx) && has_length(s) && m_util.str.is_empty(r) && !upper_bound(s, hi)) {
 | 
			
		||||
        //std::cout << "max length " << mk_pp(s, m) << " " << idx << "\n";
 | 
			
		||||
        propagate_lit(deps, 0, 0, mk_literal(m_autil.mk_le(m_util.str.mk_length(s), m_autil.mk_int(idx+1))));
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1008,7 +1061,7 @@ bool theory_seq::solve_ne(unsigned idx) {
 | 
			
		|||
            }
 | 
			
		||||
            TRACE("seq",
 | 
			
		||||
                  for (unsigned j = 0; j < lhs.size(); ++j) {
 | 
			
		||||
                      tout << mk_pp(lhs[j].get(), m) << " ";
 | 
			
		||||
                      tout << mk_pp(lhs[j].get(), m) << " " << mk_pp(rhs[j].get(), m) << "\n";
 | 
			
		||||
                  }
 | 
			
		||||
                  tout << "\n";
 | 
			
		||||
                  tout << n.ls(i) << " != " << n.rs(i) << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			@ -1018,10 +1071,9 @@ bool theory_seq::solve_ne(unsigned idx) {
 | 
			
		|||
                expr* nr = rhs[j].get();
 | 
			
		||||
                if (m_util.is_seq(nl) || m_util.is_re(nl)) {
 | 
			
		||||
                    ls.reset();
 | 
			
		||||
                     rs.reset();
 | 
			
		||||
                    SASSERT(!m_util.str.is_concat(nl));
 | 
			
		||||
                    SASSERT(!m_util.str.is_concat(nr));
 | 
			
		||||
                    ls.push_back(nl); rs.push_back(nr);
 | 
			
		||||
                    rs.reset(); 
 | 
			
		||||
                    m_util.str.get_concat(nl, ls);
 | 
			
		||||
                    m_util.str.get_concat(nr, rs);
 | 
			
		||||
                    new_ls.push_back(ls);
 | 
			
		||||
                    new_rs.push_back(rs);
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -1253,6 +1305,7 @@ void theory_seq::collect_statistics(::statistics & st) const {
 | 
			
		|||
    st.update("seq solve !=", m_stats.m_solve_nqs);
 | 
			
		||||
    st.update("seq solve =", m_stats.m_solve_eqs);
 | 
			
		||||
    st.update("seq add axiom", m_stats.m_add_axiom);
 | 
			
		||||
    st.update("seq extensionality", m_stats.m_extensionality);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void theory_seq::init_model(expr_ref_vector const& es) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1539,8 +1592,9 @@ void theory_seq::propagate() {
 | 
			
		|||
        ++m_axioms_head;
 | 
			
		||||
    }
 | 
			
		||||
    while (!m_replay.empty() && !ctx.inconsistent()) {
 | 
			
		||||
        (*m_replay[m_replay.size()-1])(*this);
 | 
			
		||||
        TRACE("seq", tout << "replay at level: " << ctx.get_scope_level() << "\n";);
 | 
			
		||||
        apply* app = m_replay[m_replay.size() - 1];
 | 
			
		||||
        (*app)(*this);
 | 
			
		||||
        m_replay.pop_back();
 | 
			
		||||
    }
 | 
			
		||||
    if (m_new_solution) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1592,7 +1646,7 @@ void theory_seq::deque_axiom(expr* n) {
 | 
			
		|||
  lit or s = "" or !prefix(s, x*s1)
 | 
			
		||||
*/
 | 
			
		||||
void theory_seq::tightest_prefix(expr* s, expr* x, literal lit1, literal lit2) {
 | 
			
		||||
    expr_ref s1 = mk_skolem(m_seq_first, s);
 | 
			
		||||
    expr_ref s1 = mk_first(s);
 | 
			
		||||
    expr_ref c  = mk_last(s);
 | 
			
		||||
    expr_ref s1c = mk_concat(s1, m_util.str.mk_unit(c));
 | 
			
		||||
    literal s_eq_emp = mk_eq_empty(s);
 | 
			
		||||
| 
						 | 
				
			
			@ -1628,30 +1682,34 @@ void theory_seq::tightest_prefix(expr* s, expr* x, literal lit1, literal lit2) {
 | 
			
		|||
   (len(s) <= len(t) -> i <= len(t)-len(s))
 | 
			
		||||
*/
 | 
			
		||||
void theory_seq::add_indexof_axiom(expr* i) {
 | 
			
		||||
    expr* s, *t, *offset;
 | 
			
		||||
    expr* s, *t, *offset = 0;
 | 
			
		||||
    rational r;
 | 
			
		||||
    VERIFY(m_util.str.is_index(i, t, s, offset));
 | 
			
		||||
    VERIFY(m_util.str.is_index(i, t, s) ||
 | 
			
		||||
           m_util.str.is_index(i, t, s, offset));
 | 
			
		||||
    expr_ref minus_one(m_autil.mk_int(-1), m);
 | 
			
		||||
    expr_ref zero(m_autil.mk_int(0), m);
 | 
			
		||||
    expr_ref xsy(m);
 | 
			
		||||
 | 
			
		||||
    // offset >= len(t) => indexof(s, t, offset) = -1
 | 
			
		||||
    expr_ref len_t(m_util.str.mk_length(t), m);
 | 
			
		||||
    literal offset_ge_len = mk_literal(m_autil.mk_ge(mk_sub(offset, len_t), zero));
 | 
			
		||||
    add_axiom(offset_ge_len, mk_eq(i, minus_one, false));
 | 
			
		||||
 | 
			
		||||
    if (m_autil.is_numeral(offset, r) && r.is_zero()) {
 | 
			
		||||
    if (!offset || (m_autil.is_numeral(offset, r) && r.is_zero())) {
 | 
			
		||||
        expr_ref x  = mk_skolem(m_contains_left, t, s);
 | 
			
		||||
        expr_ref y  = mk_skolem(m_contains_right, t, s);
 | 
			
		||||
        xsy         = mk_concat(x,s,y);
 | 
			
		||||
        xsy         = mk_concat(x, s, y);
 | 
			
		||||
        literal cnt = mk_literal(m_util.str.mk_contains(t, s));
 | 
			
		||||
        literal eq_empty = mk_eq_empty(s);
 | 
			
		||||
        add_axiom(cnt,  mk_eq(i, minus_one, false));
 | 
			
		||||
        add_axiom(~eq_empty, mk_eq(i, zero, false));
 | 
			
		||||
        add_axiom(eq_empty, ~mk_eq_empty(t), mk_eq(i, minus_one, false));
 | 
			
		||||
        add_axiom(~cnt, eq_empty, mk_eq(t, xsy, false));
 | 
			
		||||
        tightest_prefix(s, x, ~cnt);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        // offset >= len(t) => indexof(s, t, offset) = -1
 | 
			
		||||
 | 
			
		||||
        expr_ref len_t(m_util.str.mk_length(t), m);
 | 
			
		||||
        literal offset_ge_len = mk_literal(m_autil.mk_ge(mk_sub(offset, len_t), zero));
 | 
			
		||||
        add_axiom(offset_ge_len, mk_eq(i, minus_one, false));
 | 
			
		||||
 | 
			
		||||
        expr_ref x = mk_skolem(m_indexof_left, t, s, offset);
 | 
			
		||||
        expr_ref y = mk_skolem(m_indexof_right, t, s, offset);
 | 
			
		||||
        expr_ref indexof0(m_util.str.mk_index(y, s, zero), m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1922,18 +1980,18 @@ void theory_seq::add_extract_axiom(expr* e) {
 | 
			
		|||
    expr_ref ls(m_util.str.mk_length(s), m);
 | 
			
		||||
    expr_ref lx(m_util.str.mk_length(x), m);
 | 
			
		||||
    expr_ref le(m_util.str.mk_length(e), m);
 | 
			
		||||
    expr_ref ls_minus_i(mk_sub(ls, i), m);
 | 
			
		||||
    expr_ref ls_minus_i_l(mk_sub(mk_sub(ls, i),l), m);
 | 
			
		||||
    expr_ref xe = mk_concat(x, e);
 | 
			
		||||
    expr_ref zero(m_autil.mk_int(0), m);
 | 
			
		||||
 | 
			
		||||
    literal i_ge_0  = mk_literal(m_autil.mk_ge(i, zero));
 | 
			
		||||
    literal i_ge_ls = mk_literal(m_autil.mk_ge(mk_sub(i, ls), zero));
 | 
			
		||||
    literal l_ge_ls = mk_literal(m_autil.mk_ge(mk_sub(l, ls), zero));
 | 
			
		||||
    literal li_ge_ls = mk_literal(m_autil.mk_ge(ls_minus_i_l, zero));
 | 
			
		||||
    literal l_ge_zero = mk_literal(m_autil.mk_ge(l, zero));
 | 
			
		||||
 | 
			
		||||
    add_axiom(~i_ge_0, i_ge_ls, mk_literal(m_util.str.mk_prefix(xe, s)));
 | 
			
		||||
    add_axiom(~i_ge_0, i_ge_ls, mk_eq(lx, i, false));
 | 
			
		||||
    add_axiom(~i_ge_0, i_ge_ls, ~l_ge_ls, mk_eq(le, ls_minus_i, false));
 | 
			
		||||
    add_axiom(~i_ge_0, i_ge_ls, ~li_ge_ls, mk_eq(le, l, false));
 | 
			
		||||
    add_axiom(~i_ge_0, i_ge_ls, l_ge_zero, mk_eq(le, zero, false));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1947,8 +2005,8 @@ void theory_seq::add_at_axiom(expr* e) {
 | 
			
		|||
    expr* s, *i;
 | 
			
		||||
    VERIFY(m_util.str.is_at(e, s, i));
 | 
			
		||||
    expr_ref x(m), y(m), lx(m), le(m), xey(m), zero(m), one(m), len_e(m), len_x(m);
 | 
			
		||||
    x     = mk_skolem(m_at_left, s);
 | 
			
		||||
    y     = mk_skolem(m_at_right, s);
 | 
			
		||||
    x     = mk_skolem(m_at_left, s, i);
 | 
			
		||||
    y     = mk_skolem(m_at_right, s, i);
 | 
			
		||||
    xey   = mk_concat(x, e, y);
 | 
			
		||||
    zero  = m_autil.mk_int(0);
 | 
			
		||||
    one   = m_autil.mk_int(1);
 | 
			
		||||
| 
						 | 
				
			
			@ -2027,6 +2085,15 @@ literal theory_seq::mk_eq_empty(expr* _e) {
 | 
			
		|||
    expr_ref e(_e, m);
 | 
			
		||||
    SASSERT(m_util.is_seq(e));
 | 
			
		||||
    expr_ref emp(m);
 | 
			
		||||
    zstring s;
 | 
			
		||||
    if (m_util.str.is_string(e, s)) {
 | 
			
		||||
        if (s.length() == 0) {
 | 
			
		||||
            return true_literal;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return false_literal;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    emp = m_util.str.mk_empty(m.get_sort(e));
 | 
			
		||||
    return mk_equals(e, emp);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -2034,10 +2101,11 @@ literal theory_seq::mk_eq_empty(expr* _e) {
 | 
			
		|||
void theory_seq::add_axiom(literal l1, literal l2, literal l3, literal l4) {
 | 
			
		||||
    context& ctx = get_context();
 | 
			
		||||
    literal_vector lits;
 | 
			
		||||
    if (l1 != null_literal) { ctx.mark_as_relevant(l1); lits.push_back(l1); }
 | 
			
		||||
    if (l2 != null_literal) { ctx.mark_as_relevant(l2); lits.push_back(l2); }
 | 
			
		||||
    if (l3 != null_literal) { ctx.mark_as_relevant(l3); lits.push_back(l3); }
 | 
			
		||||
    if (l4 != null_literal) { ctx.mark_as_relevant(l4); lits.push_back(l4); }
 | 
			
		||||
    if (l1 == true_literal || l2 == true_literal || l3 == true_literal || l4 == true_literal) return;
 | 
			
		||||
    if (l1 != null_literal && l1 != false_literal) { ctx.mark_as_relevant(l1); lits.push_back(l1); }
 | 
			
		||||
    if (l2 != null_literal && l2 != false_literal) { ctx.mark_as_relevant(l2); lits.push_back(l2); }
 | 
			
		||||
    if (l3 != null_literal && l3 != false_literal) { ctx.mark_as_relevant(l3); lits.push_back(l3); }
 | 
			
		||||
    if (l4 != null_literal && l4 != false_literal) { ctx.mark_as_relevant(l4); lits.push_back(l4); }
 | 
			
		||||
    TRACE("seq", ctx.display_literals_verbose(tout << "axiom: ", lits.size(), lits.c_ptr()); tout << "\n";);
 | 
			
		||||
    m_new_propagation = true;
 | 
			
		||||
    ++m_stats.m_add_axiom;
 | 
			
		||||
| 
						 | 
				
			
			@ -2077,8 +2145,8 @@ void theory_seq::propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs)
 | 
			
		|||
 | 
			
		||||
    }
 | 
			
		||||
    TRACE("seq",
 | 
			
		||||
          tout << mk_pp(ctx.bool_var2expr(lit.var()), m) << " => "
 | 
			
		||||
          << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
 | 
			
		||||
          ctx.display_literals_verbose(tout, 1, &lit);
 | 
			
		||||
          tout << " => " << mk_pp(e1, m) << " = " << mk_pp(e2, m) << "\n";);
 | 
			
		||||
    justification* js =
 | 
			
		||||
        ctx.mk_justification(
 | 
			
		||||
            ext_theory_eq_propagation_justification(
 | 
			
		||||
| 
						 | 
				
			
			@ -2121,7 +2189,7 @@ void theory_seq::assign_eh(bool_var v, bool is_true) {
 | 
			
		|||
            propagate_non_empty(lit, e1);
 | 
			
		||||
 | 
			
		||||
            // lit => e1 = first ++ (unit last)
 | 
			
		||||
            expr_ref f1 = mk_skolem(m_seq_first, e1);
 | 
			
		||||
            expr_ref f1 = mk_first(e1);
 | 
			
		||||
            expr_ref f2 = mk_last(e1);
 | 
			
		||||
            f = mk_concat(f1, m_util.str.mk_unit(f2));
 | 
			
		||||
            propagate_eq(lit, e1, f, true);
 | 
			
		||||
| 
						 | 
				
			
			@ -2231,6 +2299,7 @@ void theory_seq::push_scope_eh() {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
void theory_seq::pop_scope_eh(unsigned num_scopes) {
 | 
			
		||||
    context& ctx = get_context();
 | 
			
		||||
    m_trail_stack.pop_scope(num_scopes);
 | 
			
		||||
    theory::pop_scope_eh(num_scopes);
 | 
			
		||||
    m_dm.pop_scope(num_scopes);
 | 
			
		||||
| 
						 | 
				
			
			@ -2240,6 +2309,10 @@ void theory_seq::pop_scope_eh(unsigned num_scopes) {
 | 
			
		|||
    m_nqs.pop_scope(num_scopes);
 | 
			
		||||
    m_atoms.resize(m_atoms_lim[m_atoms_lim.size()-num_scopes]);
 | 
			
		||||
    m_atoms_lim.shrink(m_atoms_lim.size()-num_scopes);
 | 
			
		||||
    m_rewrite.reset();    
 | 
			
		||||
    if (ctx.get_base_level() > ctx.get_scope_level() - num_scopes) {
 | 
			
		||||
        m_replay.reset();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void theory_seq::restart_eh() {
 | 
			
		||||
| 
						 | 
				
			
			@ -2566,7 +2639,8 @@ bool theory_seq::add_prefix2prefix(expr* e) {
 | 
			
		|||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
    expr_ref emp(m_util.str.mk_empty(m.get_sort(e1)), m);
 | 
			
		||||
    switch (assume_equality(e2, emp)) {
 | 
			
		||||
    literal e2_is_emp = mk_eq_empty(e2);
 | 
			
		||||
    switch (ctx.get_assignment(e2_is_emp)) {
 | 
			
		||||
    case l_true:
 | 
			
		||||
        return false; // done
 | 
			
		||||
    case l_undef:
 | 
			
		||||
| 
						 | 
				
			
			@ -2574,16 +2648,19 @@ bool theory_seq::add_prefix2prefix(expr* e) {
 | 
			
		|||
    default:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    expr_ref head1(m), tail1(m), head2(m), tail2(m);
 | 
			
		||||
 | 
			
		||||
    expr_ref head1(m), tail1(m), head2(m), tail2(m), conc(m);
 | 
			
		||||
    mk_decompose(e1, head1, tail1);
 | 
			
		||||
    mk_decompose(e2, head2, tail2);
 | 
			
		||||
    conc = mk_concat(head2, tail2);
 | 
			
		||||
    propagate_eq(~e2_is_emp, e2, conc, true);
 | 
			
		||||
 | 
			
		||||
    literal lit = mk_eq(head1, head2, false);
 | 
			
		||||
    switch (ctx.get_assignment(lit)) {
 | 
			
		||||
    case l_true: {
 | 
			
		||||
        literal_vector lits;
 | 
			
		||||
        lits.push_back(~ctx.get_literal(e));
 | 
			
		||||
        lits.push_back(~mk_eq(e2, emp, false));
 | 
			
		||||
        lits.push_back(~e2_is_emp);
 | 
			
		||||
        lits.push_back(lit);
 | 
			
		||||
        propagate_lit(0, lits.size(), lits.c_ptr(), ~mk_literal(m_util.str.mk_prefix(tail1, tail2)));
 | 
			
		||||
        return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -2610,28 +2687,32 @@ bool theory_seq::add_suffix2suffix(expr* e) {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    expr_ref emp(m_util.str.mk_empty(m.get_sort(e1)), m);
 | 
			
		||||
 | 
			
		||||
    switch (assume_equality(e2, emp)) {
 | 
			
		||||
    literal e2_is_emp = mk_eq_empty(e2);
 | 
			
		||||
    switch (ctx.get_assignment(e2_is_emp)) {
 | 
			
		||||
    case l_true:
 | 
			
		||||
        TRACE("seq", tout << mk_pp(e, m) << " " << mk_pp(e2, m) << " is empty\n";);
 | 
			
		||||
        return false; // done
 | 
			
		||||
    case l_undef:
 | 
			
		||||
        ctx.force_phase(mk_eq(e2, emp, false));
 | 
			
		||||
        TRACE("seq", tout << mk_pp(e, m) << " " << mk_pp(e2, m) << " is unassigned\n";);
 | 
			
		||||
        ctx.force_phase(e2_is_emp);
 | 
			
		||||
        return true;  // retry
 | 
			
		||||
    case l_false:
 | 
			
		||||
        break;
 | 
			
		||||
    }
 | 
			
		||||
    expr_ref first2 = mk_skolem(m_seq_first, e2);
 | 
			
		||||
    expr_ref first2 = mk_first(e2);
 | 
			
		||||
    expr_ref last2  = mk_last(e2);
 | 
			
		||||
    expr_ref first1 = mk_skolem(m_seq_first, e1);
 | 
			
		||||
    expr_ref first1 = mk_first(e1);
 | 
			
		||||
    expr_ref last1  = mk_last(e1);
 | 
			
		||||
    expr_ref conc = mk_concat(first2, m_util.str.mk_unit(last2));
 | 
			
		||||
    propagate_eq(~mk_eq(e2, emp, false), e2, conc);
 | 
			
		||||
    propagate_eq(~e2_is_emp, e2, conc, true);
 | 
			
		||||
 | 
			
		||||
    literal last_eq = mk_eq(last1, last2, false);
 | 
			
		||||
    switch (ctx.get_assignment(last_eq)) {
 | 
			
		||||
    case l_false:
 | 
			
		||||
        TRACE("seq", tout << mk_pp(e, m) << " " << last1 << " = " << last2 << " is false\n";);
 | 
			
		||||
        return false; // done
 | 
			
		||||
    case l_undef:
 | 
			
		||||
        TRACE("seq", tout << mk_pp(e, m) << " " << last1 << " = " << last2 << " is unassigned\n";);
 | 
			
		||||
        ctx.force_phase(~last_eq);
 | 
			
		||||
        return true;
 | 
			
		||||
    case l_true:
 | 
			
		||||
| 
						 | 
				
			
			@ -2640,9 +2721,10 @@ bool theory_seq::add_suffix2suffix(expr* e) {
 | 
			
		|||
 | 
			
		||||
    literal_vector lits;
 | 
			
		||||
    lits.push_back(~ctx.get_literal(e));
 | 
			
		||||
    lits.push_back(~mk_eq(e2, emp, false));
 | 
			
		||||
    lits.push_back(~e2_is_emp);
 | 
			
		||||
    lits.push_back(last_eq);
 | 
			
		||||
    propagate_lit(0, lits.size(), lits.c_ptr(), ~mk_literal(m_util.str.mk_suffix(first1, first2)));
 | 
			
		||||
    TRACE("seq", tout << mk_pp(e, m) << " saturate\n";);
 | 
			
		||||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -192,6 +192,7 @@ namespace smt {
 | 
			
		|||
            expr_ref m_e;
 | 
			
		||||
        public:
 | 
			
		||||
            replay_length_coherence(ast_manager& m, expr* e) : m_e(e, m) {}
 | 
			
		||||
            virtual ~replay_length_coherence() {}
 | 
			
		||||
            virtual void operator()(theory_seq& th) {
 | 
			
		||||
                th.check_length_coherence(m_e);
 | 
			
		||||
                m_e.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -202,6 +203,7 @@ namespace smt {
 | 
			
		|||
            expr_ref m_e;
 | 
			
		||||
        public:
 | 
			
		||||
            replay_axiom(ast_manager& m, expr* e) : m_e(e, m) {}
 | 
			
		||||
            virtual ~replay_axiom() {}
 | 
			
		||||
            virtual void operator()(theory_seq& th) {
 | 
			
		||||
                th.enque_axiom(m_e);
 | 
			
		||||
                m_e.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -239,6 +241,7 @@ namespace smt {
 | 
			
		|||
            unsigned m_solve_nqs;
 | 
			
		||||
            unsigned m_solve_eqs;
 | 
			
		||||
            unsigned m_add_axiom;
 | 
			
		||||
            unsigned m_extensionality;
 | 
			
		||||
        };
 | 
			
		||||
        ast_manager&               m;
 | 
			
		||||
        dependency_manager         m_dm;
 | 
			
		||||
| 
						 | 
				
			
			@ -312,6 +315,7 @@ namespace smt {
 | 
			
		|||
        bool check_length_coherence(expr* e);
 | 
			
		||||
        bool propagate_length_coherence(expr* e);  
 | 
			
		||||
 | 
			
		||||
        bool check_extensionality();
 | 
			
		||||
        bool solve_eqs(unsigned start);
 | 
			
		||||
        bool solve_eq(expr_ref_vector const& l, expr_ref_vector const& r, dependency* dep);
 | 
			
		||||
        bool simplify_eq(expr_ref_vector& l, expr_ref_vector& r, dependency* dep);
 | 
			
		||||
| 
						 | 
				
			
			@ -334,7 +338,7 @@ namespace smt {
 | 
			
		|||
        void propagate_lit(dependency* dep, literal lit) { propagate_lit(dep, 0, 0, lit); }
 | 
			
		||||
        void propagate_lit(dependency* dep, unsigned n, literal const* lits, literal lit);
 | 
			
		||||
        void propagate_eq(dependency* dep, enode* n1, enode* n2);
 | 
			
		||||
        void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs = false);
 | 
			
		||||
        void propagate_eq(literal lit, expr* e1, expr* e2, bool add_to_eqs);
 | 
			
		||||
        void set_conflict(dependency* dep, literal_vector const& lits = literal_vector());
 | 
			
		||||
 | 
			
		||||
        u_map<unsigned> m_branch_start;
 | 
			
		||||
| 
						 | 
				
			
			@ -353,6 +357,7 @@ namespace smt {
 | 
			
		|||
        bool is_tail(expr* a, expr*& s, unsigned& idx) const;
 | 
			
		||||
        expr_ref mk_nth(expr* s, expr* idx);
 | 
			
		||||
        expr_ref mk_last(expr* e);
 | 
			
		||||
        expr_ref mk_first(expr* e);
 | 
			
		||||
        expr_ref canonize(expr* e, dependency*& eqs);
 | 
			
		||||
        bool canonize(expr* e, expr_ref_vector& es, dependency*& eqs);
 | 
			
		||||
        bool canonize(expr_ref_vector const& es, expr_ref_vector& result, dependency*& eqs);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,6 +51,7 @@ public:
 | 
			
		|||
    virtual void get_model(model_ref & m) = 0;
 | 
			
		||||
    virtual proof * get_proof() = 0;
 | 
			
		||||
    virtual std::string reason_unknown() const = 0;
 | 
			
		||||
    virtual void set_reason_unknown(char const* msg) = 0;
 | 
			
		||||
    virtual void get_labels(svector<symbol> & r) = 0;
 | 
			
		||||
    virtual ast_manager& get_manager() = 0;
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			@ -75,6 +76,7 @@ struct simple_check_sat_result : public check_sat_result {
 | 
			
		|||
    virtual proof * get_proof();
 | 
			
		||||
    virtual std::string reason_unknown() const;
 | 
			
		||||
    virtual void get_labels(svector<symbol> & r);
 | 
			
		||||
    virtual void set_reason_unknown(char const* msg) { m_unknown = msg; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -297,6 +297,11 @@ public:
 | 
			
		|||
            return m_solver2->reason_unknown();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void set_reason_unknown(char const* msg) {
 | 
			
		||||
        m_solver1->set_reason_unknown(msg);
 | 
			
		||||
        m_solver2->set_reason_unknown(msg);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    virtual void get_labels(svector<symbol> & r) {
 | 
			
		||||
        if (m_use_solver1_results)
 | 
			
		||||
            return m_solver1->get_labels(r);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -65,6 +65,7 @@ public:
 | 
			
		|||
    virtual void get_model(model_ref & m);
 | 
			
		||||
    virtual proof * get_proof();
 | 
			
		||||
    virtual std::string reason_unknown() const;
 | 
			
		||||
    virtual void set_reason_unknown(char const* msg);
 | 
			
		||||
    virtual void get_labels(svector<symbol> & r) {}
 | 
			
		||||
 | 
			
		||||
    virtual void set_progress_callback(progress_callback * callback) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -225,6 +226,12 @@ std::string tactic2solver::reason_unknown() const {
 | 
			
		|||
        return std::string("unknown");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void tactic2solver::set_reason_unknown(char const* msg) {
 | 
			
		||||
    if (m_result.get()) {
 | 
			
		||||
        m_result->set_reason_unknown(msg);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned tactic2solver::get_num_assertions() const {
 | 
			
		||||
    return m_assertions.size();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -384,7 +384,7 @@ void fpa2bv_model_converter::convert(model * bv_mdl, model * float_mdl) {
 | 
			
		|||
        if (!seen.contains(f))
 | 
			
		||||
        {
 | 
			
		||||
            TRACE("fpa2bv_mc", tout << "Keeping: " << mk_ismt2_pp(f, m) << std::endl;);
 | 
			
		||||
            func_interp * val = bv_mdl->get_func_interp(f);
 | 
			
		||||
            func_interp * val = bv_mdl->get_func_interp(f)->copy();
 | 
			
		||||
            float_mdl->register_decl(f, val);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue