mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	Merge branch 'unstable' of https://git01.codeplex.com/z3 into fpa-api
Conflicts: src/ast/float_decl_plugin.h Signed-off-by: Christoph M. Wintersteiger <cwinter@microsoft.com>
This commit is contained in:
		
						commit
						c508b66cf7
					
				
					 37 changed files with 502 additions and 263 deletions
				
			
		| 
						 | 
				
			
			@ -1630,9 +1630,7 @@ public:
 | 
			
		|||
                unsigned parent_id = Z3_get_ast_id(ctx, p.arg(0));
 | 
			
		||||
                std::set<unsigned> const& hyps = m_proof_hypotheses.find(parent_id)->second;
 | 
			
		||||
                print_hypotheses(out, hyps);
 | 
			
		||||
                out << ").\n";
 | 
			
		||||
                break;                
 | 
			
		||||
                display_inference(out, "lemma", "thm", p);
 | 
			
		||||
                out << "))).\n";
 | 
			
		||||
                break;                
 | 
			
		||||
            }     
 | 
			
		||||
            case Z3_OP_PR_UNIT_RESOLUTION:                                 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,7 +80,7 @@ GPROF=False
 | 
			
		|||
GIT_HASH=False
 | 
			
		||||
 | 
			
		||||
def check_output(cmd):
 | 
			
		||||
    return subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0].rstrip('\r\n')
 | 
			
		||||
    return str(subprocess.Popen(cmd, stdout=subprocess.PIPE).communicate()[0]).rstrip('\r\n')
 | 
			
		||||
 | 
			
		||||
def git_hash():
 | 
			
		||||
    try:
 | 
			
		||||
| 
						 | 
				
			
			@ -764,7 +764,7 @@ class Component:
 | 
			
		|||
        out.write('\n')
 | 
			
		||||
        mk_dir(os.path.join(BUILD_DIR, self.build_dir))
 | 
			
		||||
        if VS_PAR and IS_WINDOWS:
 | 
			
		||||
            cppfiles = get_cpp_files(self.src_dir)
 | 
			
		||||
            cppfiles = list(get_cpp_files(self.src_dir))
 | 
			
		||||
            dependencies = set()
 | 
			
		||||
            for cppfile in cppfiles:
 | 
			
		||||
                dependencies.add(os.path.join(self.to_src_dir, cppfile))
 | 
			
		||||
| 
						 | 
				
			
			@ -810,6 +810,9 @@ class Component:
 | 
			
		|||
    def require_mem_initializer(self):
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def mk_install_deps(self, out):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    def mk_install(self, out):
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -853,6 +856,9 @@ class LibComponent(Component):
 | 
			
		|||
        out.write('\n')
 | 
			
		||||
        out.write('%s: %s\n\n' % (self.name, libfile))
 | 
			
		||||
 | 
			
		||||
    def mk_install_dep(self, out):
 | 
			
		||||
        out.write('%s' % libfile)
 | 
			
		||||
 | 
			
		||||
    def mk_install(self, out):
 | 
			
		||||
        for include in self.includes2install:
 | 
			
		||||
            out.write('\t@cp %s %s\n' % (os.path.join(self.to_src_dir, include), os.path.join('$(PREFIX)', 'include', include)))
 | 
			
		||||
| 
						 | 
				
			
			@ -935,6 +941,9 @@ class ExeComponent(Component):
 | 
			
		|||
    def main_component(self):
 | 
			
		||||
        return self.install
 | 
			
		||||
 | 
			
		||||
    def mk_install_dep(self, out):
 | 
			
		||||
        out.write('%s' % exefile)
 | 
			
		||||
 | 
			
		||||
    def mk_install(self, out):
 | 
			
		||||
        if self.install:
 | 
			
		||||
            exefile = '%s$(EXE_EXT)' % self.exe_name
 | 
			
		||||
| 
						 | 
				
			
			@ -1076,6 +1085,11 @@ class DLLComponent(Component):
 | 
			
		|||
    def require_def_file(self):
 | 
			
		||||
        return IS_WINDOWS and self.export_files
 | 
			
		||||
 | 
			
		||||
    def mk_install_dep(self, out):
 | 
			
		||||
        out.write('%s$(SO_EXT)' % self.dll_name)
 | 
			
		||||
        if self.static:
 | 
			
		||||
            out.write(' %s$(LIB_EXT)' % self.dll_name)
 | 
			
		||||
 | 
			
		||||
    def mk_install(self, out):
 | 
			
		||||
        if self.install:
 | 
			
		||||
            dllfile = '%s$(SO_EXT)' % self.dll_name
 | 
			
		||||
| 
						 | 
				
			
			@ -1611,7 +1625,11 @@ def mk_config():
 | 
			
		|||
                print('Java Compiler:  %s' % JAVAC)
 | 
			
		||||
 | 
			
		||||
def mk_install(out):
 | 
			
		||||
    out.write('install:\n')
 | 
			
		||||
    out.write('install: ')
 | 
			
		||||
    for c in get_components():
 | 
			
		||||
        c.mk_install_deps(out)
 | 
			
		||||
        out.write(' ')
 | 
			
		||||
    out.write('\n')
 | 
			
		||||
    out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'bin'))
 | 
			
		||||
    out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'include'))
 | 
			
		||||
    out.write('\t@mkdir -p %s\n' % os.path.join('$(PREFIX)', 'lib'))
 | 
			
		||||
| 
						 | 
				
			
			@ -2573,16 +2591,17 @@ def mk_vs_proj(name, components):
 | 
			
		|||
def mk_win_dist(build_path, dist_path):
 | 
			
		||||
    for c in get_components():
 | 
			
		||||
        c.mk_win_dist(build_path, dist_path)
 | 
			
		||||
    # Add Z3Py to lib directory
 | 
			
		||||
    for pyc in filter(lambda f: f.endswith('.pyc'), os.listdir(build_path)):
 | 
			
		||||
    # Add Z3Py to bin directory
 | 
			
		||||
    print("Adding to %s\n" % dist_path)
 | 
			
		||||
    for pyc in filter(lambda f: f.endswith('.pyc') or f.endswith('.py'), os.listdir(build_path)):
 | 
			
		||||
        shutil.copy(os.path.join(build_path, pyc),
 | 
			
		||||
                    os.path.join(dist_path, 'bin', pyc))
 | 
			
		||||
 | 
			
		||||
def mk_unix_dist(build_path, dist_path):
 | 
			
		||||
    for c in get_components():
 | 
			
		||||
        c.mk_unix_dist(build_path, dist_path)
 | 
			
		||||
    # Add Z3Py to lib directory
 | 
			
		||||
    for pyc in filter(lambda f: f.endswith('.pyc'), os.listdir(build_path)):
 | 
			
		||||
    # Add Z3Py to bin directory
 | 
			
		||||
    for pyc in filter(lambda f: f.endswith('.pyc') or f.endswith('.py'), os.listdir(build_path)):
 | 
			
		||||
        shutil.copy(os.path.join(build_path, pyc),
 | 
			
		||||
                    os.path.join(dist_path, 'bin', pyc))
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -269,6 +269,14 @@ namespace Microsoft.Z3
 | 
			
		|||
                             AST.ArrayLength(queries), AST.ArrayToNative(queries));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        BoolExpr[] ToBoolExprs(ASTVector v) {
 | 
			
		||||
            uint n = v.Size;
 | 
			
		||||
            BoolExpr[] res = new BoolExpr[n];
 | 
			
		||||
            for (uint i = 0; i < n; i++)
 | 
			
		||||
                res[i] = new BoolExpr(Context, v[i].NativeObject);
 | 
			
		||||
            return res;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Retrieve set of rules added to fixedpoint context.
 | 
			
		||||
        /// </summary>                
 | 
			
		||||
| 
						 | 
				
			
			@ -278,12 +286,7 @@ namespace Microsoft.Z3
 | 
			
		|||
            {
 | 
			
		||||
                Contract.Ensures(Contract.Result<BoolExpr[]>() != null);
 | 
			
		||||
 | 
			
		||||
                ASTVector v = new ASTVector(Context, Native.Z3_fixedpoint_get_rules(Context.nCtx, NativeObject));
 | 
			
		||||
                uint n = v.Size;
 | 
			
		||||
                BoolExpr[] res = new BoolExpr[n];
 | 
			
		||||
                for (uint i = 0; i < n; i++)
 | 
			
		||||
                    res[i] = new BoolExpr(Context, v[i].NativeObject);
 | 
			
		||||
                return res;
 | 
			
		||||
                return ToBoolExprs(new ASTVector(Context, Native.Z3_fixedpoint_get_rules(Context.nCtx, NativeObject)));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -296,15 +299,27 @@ namespace Microsoft.Z3
 | 
			
		|||
            {
 | 
			
		||||
                Contract.Ensures(Contract.Result<BoolExpr[]>() != null);
 | 
			
		||||
 | 
			
		||||
                ASTVector v = new ASTVector(Context, Native.Z3_fixedpoint_get_assertions(Context.nCtx, NativeObject));
 | 
			
		||||
                uint n = v.Size;
 | 
			
		||||
                BoolExpr[] res = new BoolExpr[n];
 | 
			
		||||
                for (uint i = 0; i < n; i++)
 | 
			
		||||
                    res[i] = new BoolExpr(Context, v[i].NativeObject);
 | 
			
		||||
                return res;
 | 
			
		||||
                return ToBoolExprs(new ASTVector(Context, Native.Z3_fixedpoint_get_assertions(Context.nCtx, NativeObject)));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Parse an SMT-LIB2 file with fixedpoint rules. 
 | 
			
		||||
        /// Add the rules to the current fixedpoint context. 
 | 
			
		||||
        /// Return the set of queries in the file.
 | 
			
		||||
        /// </summary>                
 | 
			
		||||
	public BoolExpr[] ParseFile(string file) {
 | 
			
		||||
            return ToBoolExprs(new ASTVector(Context, Native.Z3_fixedpoint_from_file(Context.nCtx, NativeObject, file)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Similar to ParseFile. Instead it takes as argument a string.
 | 
			
		||||
        /// </summary>                
 | 
			
		||||
 | 
			
		||||
	public BoolExpr[] ParseString(string s) {
 | 
			
		||||
            return ToBoolExprs(new ASTVector(Context, Native.Z3_fixedpoint_from_string(Context.nCtx, NativeObject, s)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        #region Internal
 | 
			
		||||
        internal Fixedpoint(Context ctx, IntPtr obj)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5670,7 +5670,8 @@ END_MLAPI_EXCLUDE
 | 
			
		|||
       Each conjunct encodes values of the bound variables of the query that are satisfied.
 | 
			
		||||
       In PDR mode, the returned answer is a single conjunction.
 | 
			
		||||
 | 
			
		||||
       The previous call to Z3_fixedpoint_query must have returned Z3_L_TRUE.
 | 
			
		||||
       When used in Datalog mode the previous call to Z3_fixedpoint_query must have returned Z3_L_TRUE.
 | 
			
		||||
       When used with the PDR engine, the previous call must have been either Z3_L_TRUE or Z3_L_FALSE.
 | 
			
		||||
 | 
			
		||||
       def_API('Z3_fixedpoint_get_answer', AST, (_in(CONTEXT), _in(FIXEDPOINT)))
 | 
			
		||||
    */    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -569,8 +569,8 @@ class smt_printer {
 | 
			
		|||
            m_out << ")";
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        if (m_is_smt2 && q->get_num_patterns() > 0) {
 | 
			
		||||
            m_out << "(!";
 | 
			
		||||
        if (m_is_smt2 && (q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
 | 
			
		||||
            m_out << "(! ";
 | 
			
		||||
        }
 | 
			
		||||
        {
 | 
			
		||||
            smt_printer p(m_out, m_manager, m_qlists, m_renaming, m_logic, false, m_is_smt2, m_simplify_implies, m_indent, m_num_var_names, m_var_names);        
 | 
			
		||||
| 
						 | 
				
			
			@ -609,7 +609,11 @@ class smt_printer {
 | 
			
		|||
                m_out << "}";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        if (m_is_smt2 && q->get_num_patterns() > 0) {
 | 
			
		||||
 | 
			
		||||
        if (q->get_qid() != symbol::null)
 | 
			
		||||
            m_out << " :qid " << q->get_qid();
 | 
			
		||||
 | 
			
		||||
        if (m_is_smt2 && (q->get_num_patterns() > 0 || q->get_qid() != symbol::null)) {
 | 
			
		||||
            m_out << ")";
 | 
			
		||||
        }
 | 
			
		||||
        m_out << ")";
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -106,7 +106,7 @@ bool float_decl_plugin::is_value(expr * n, mpf & val) {
 | 
			
		|||
    return false;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool float_decl_plugin::is_rm(expr * n, mpf_rounding_mode & val) {
 | 
			
		||||
bool float_decl_plugin::is_rm_value(expr * n, mpf_rounding_mode & val) {
 | 
			
		||||
    if (is_app_of(n, m_family_id, OP_RM_NEAREST_TIES_TO_AWAY)) {
 | 
			
		||||
        val = MPF_ROUND_NEAREST_TAWAY;
 | 
			
		||||
        return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,7 +169,8 @@ public:
 | 
			
		|||
    app * mk_value(mpf const & v);
 | 
			
		||||
    bool is_value(expr * n) { return is_app_of(n, m_family_id, OP_FLOAT_VALUE); }
 | 
			
		||||
    bool is_value(expr * n, mpf & val);
 | 
			
		||||
    bool is_rm(expr * n, mpf_rounding_mode & val);
 | 
			
		||||
    bool is_rm_value(expr * n, mpf_rounding_mode & val);
 | 
			
		||||
    bool is_rm_value(expr * n) { mpf_rounding_mode t; return is_rm_value(n, t); }
 | 
			
		||||
 | 
			
		||||
    mpf const & get_value(unsigned id) const { 
 | 
			
		||||
        SASSERT(m_value_table.contains(id));
 | 
			
		||||
| 
						 | 
				
			
			@ -200,6 +201,8 @@ public:
 | 
			
		|||
    sort * mk_rm_sort() { return m().mk_sort(m_fid, ROUNDING_MODE_SORT); }
 | 
			
		||||
    bool is_float(sort * s) { return is_sort_of(s, m_fid, FLOAT_SORT); }
 | 
			
		||||
    bool is_rm(sort * s) { return is_sort_of(s, m_fid, ROUNDING_MODE_SORT); }
 | 
			
		||||
    bool is_float(expr * e) { return is_float(m_manager.get_sort(e)); }
 | 
			
		||||
    bool is_rm(expr * e) { return is_rm(m_manager.get_sort(e)); }
 | 
			
		||||
    unsigned get_ebits(sort * s);
 | 
			
		||||
    unsigned get_sbits(sort * s);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -217,11 +220,9 @@ public:
 | 
			
		|||
    app * mk_minus_inf(sort * s) { return mk_minus_inf(get_ebits(s), get_sbits(s)); }
 | 
			
		||||
 | 
			
		||||
    app * mk_value(mpf const & v) { return m_plugin->mk_value(v); }
 | 
			
		||||
    bool is_value(expr * n) const { return m_plugin->is_value(n); }
 | 
			
		||||
    bool is_numeral(expr * n) const { return is_value(n); }
 | 
			
		||||
    bool is_value(expr * n, mpf & v) const { return m_plugin->is_value(n, v); }    
 | 
			
		||||
    bool is_numeral(expr * n, mpf & v) const { return is_value(n, v); }    
 | 
			
		||||
    bool is_rm(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm(n, v); }    
 | 
			
		||||
    bool is_value(expr * n) { return m_plugin->is_value(n); }
 | 
			
		||||
    bool is_value(expr * n, mpf & v) { return m_plugin->is_value(n, v); }     
 | 
			
		||||
    bool is_rm_value(expr * n, mpf_rounding_mode & v) { return m_plugin->is_rm_value(n, v); }
 | 
			
		||||
 | 
			
		||||
    app * mk_pzero(unsigned ebits, unsigned sbits);
 | 
			
		||||
    app * mk_nzero(unsigned ebits, unsigned sbits);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -28,9 +28,10 @@ fpa2bv_converter::fpa2bv_converter(ast_manager & m) :
 | 
			
		|||
    m(m),
 | 
			
		||||
    m_simp(m),
 | 
			
		||||
    m_util(m),
 | 
			
		||||
    m_bv_util(m),
 | 
			
		||||
    m_arith_util(m),
 | 
			
		||||
    m_mpf_manager(m_util.fm()),
 | 
			
		||||
    m_mpz_manager(m_mpf_manager.mpz_manager()),    
 | 
			
		||||
    m_bv_util(m),
 | 
			
		||||
    extra_assertions(m) {
 | 
			
		||||
    m_plugin = static_cast<float_decl_plugin*>(m.get_plugin(m.mk_family_id("float")));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -268,7 +269,7 @@ void fpa2bv_converter::mk_rm_const(func_decl * f, expr_ref & result) {
 | 
			
		|||
        result = r;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        SASSERT(is_rm_sort(f->get_range()));
 | 
			
		||||
        SASSERT(is_rm(f->get_range()));
 | 
			
		||||
 | 
			
		||||
        result = m.mk_fresh_const(
 | 
			
		||||
            #ifdef Z3DEBUG
 | 
			
		||||
| 
						 | 
				
			
			@ -281,6 +282,10 @@ void fpa2bv_converter::mk_rm_const(func_decl * f, expr_ref & result) {
 | 
			
		|||
        m_rm_const2bv.insert(f, result);
 | 
			
		||||
        m.inc_ref(f);
 | 
			
		||||
        m.inc_ref(result);
 | 
			
		||||
 | 
			
		||||
        expr_ref rcc(m);
 | 
			
		||||
        rcc = bu().mk_ule(result, bu().mk_numeral(4, 3));
 | 
			
		||||
        extra_assertions.push_back(rcc);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1847,6 +1852,55 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a
 | 
			
		|||
        // Just keep it here, as there will be something else that uses it.
 | 
			
		||||
        mk_triple(args[0], args[1], args[2], result);
 | 
			
		||||
    }
 | 
			
		||||
    else if (num == 3 &&
 | 
			
		||||
             m_bv_util.is_bv(args[0]) &&
 | 
			
		||||
             m_arith_util.is_numeral(args[1]) &&
 | 
			
		||||
             m_arith_util.is_numeral(args[2]))
 | 
			
		||||
    {
 | 
			
		||||
        // Three arguments, some of them are not numerals.
 | 
			
		||||
        SASSERT(m_util.is_float(f->get_range()));
 | 
			
		||||
        unsigned ebits = m_util.get_ebits(f->get_range());
 | 
			
		||||
        unsigned sbits = m_util.get_sbits(f->get_range());
 | 
			
		||||
 | 
			
		||||
        expr * rm = args[0];
 | 
			
		||||
 | 
			
		||||
        rational q;
 | 
			
		||||
        if (!m_arith_util.is_numeral(args[1], q))
 | 
			
		||||
            NOT_IMPLEMENTED_YET();
 | 
			
		||||
 | 
			
		||||
        rational e;
 | 
			
		||||
        if (!m_arith_util.is_numeral(args[2], e))
 | 
			
		||||
            NOT_IMPLEMENTED_YET();
 | 
			
		||||
 | 
			
		||||
        SASSERT(e.is_int64());
 | 
			
		||||
        SASSERT(m_mpz_manager.eq(e.to_mpq().denominator(), 1));
 | 
			
		||||
 | 
			
		||||
        mpf nte, nta, tp, tn, tz;
 | 
			
		||||
        m_mpf_manager.set(nte, ebits, sbits, MPF_ROUND_NEAREST_TEVEN, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(nta, ebits, sbits, MPF_ROUND_NEAREST_TAWAY, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(tp, ebits, sbits, MPF_ROUND_TOWARD_POSITIVE, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(tn, ebits, sbits, MPF_ROUND_TOWARD_NEGATIVE, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        m_mpf_manager.set(tz, ebits, sbits, MPF_ROUND_TOWARD_ZERO, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
 | 
			
		||||
        app_ref a_nte(m), a_nta(m), a_tp(m), a_tn(m), a_tz(m);
 | 
			
		||||
        a_nte = m_plugin->mk_value(nte);
 | 
			
		||||
        a_nta = m_plugin->mk_value(nta);
 | 
			
		||||
        a_tp = m_plugin->mk_value(tp);
 | 
			
		||||
        a_tn = m_plugin->mk_value(tn);
 | 
			
		||||
        a_tz = m_plugin->mk_value(tz);
 | 
			
		||||
 | 
			
		||||
        expr_ref bv_nte(m), bv_nta(m), bv_tp(m), bv_tn(m), bv_tz(m);
 | 
			
		||||
        mk_value(a_nte->get_decl(), 0, 0, bv_nte);
 | 
			
		||||
        mk_value(a_nta->get_decl(), 0, 0, bv_nta);
 | 
			
		||||
        mk_value(a_tp->get_decl(), 0, 0, bv_tp);
 | 
			
		||||
        mk_value(a_tn->get_decl(), 0, 0, bv_tn);
 | 
			
		||||
        mk_value(a_tz->get_decl(), 0, 0, bv_tz);
 | 
			
		||||
 | 
			
		||||
        mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)), bv_tn, bv_tz, result);
 | 
			
		||||
        mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TO_POSITIVE, 3)), bv_tp, result, result);
 | 
			
		||||
        mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_AWAY, 3)), bv_nta, result, result);
 | 
			
		||||
        mk_ite(m.mk_eq(rm, m_bv_util.mk_numeral(BV_RM_TIES_TO_EVEN, 3)), bv_nte, result, result);        
 | 
			
		||||
    }
 | 
			
		||||
    else if (num == 1 && m_bv_util.is_bv(args[0])) {
 | 
			
		||||
        sort * s = f->get_range();
 | 
			
		||||
        unsigned to_sbits = m_util.get_sbits(s);
 | 
			
		||||
| 
						 | 
				
			
			@ -1862,7 +1916,9 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a
 | 
			
		|||
                  m_bv_util.mk_extract(sz - 2, sz - to_ebits - 1, bv),
 | 
			
		||||
                  result);
 | 
			
		||||
    }
 | 
			
		||||
    else if (num == 2 && is_app(args[1]) && m_util.is_float(m.get_sort(args[1]))) {        
 | 
			
		||||
    else if (num == 2 && 
 | 
			
		||||
             is_app(args[1]) && 
 | 
			
		||||
             m_util.is_float(m.get_sort(args[1]))) {        
 | 
			
		||||
        // We also support float to float conversion
 | 
			
		||||
        sort * s = f->get_range();
 | 
			
		||||
        expr_ref rm(m), x(m); 
 | 
			
		||||
| 
						 | 
				
			
			@ -2016,9 +2072,10 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a
 | 
			
		|||
            mk_ite(c1, v1, result, result);
 | 
			
		||||
        }
 | 
			
		||||
    }    
 | 
			
		||||
    else {
 | 
			
		||||
    else if (num == 2 &&              
 | 
			
		||||
             m_util.is_rm(args[0]),
 | 
			
		||||
             m_arith_util.is_real(args[1])) {
 | 
			
		||||
        // .. other than that, we only support rationals for asFloat
 | 
			
		||||
        SASSERT(num == 2);
 | 
			
		||||
        SASSERT(m_util.is_float(f->get_range()));        
 | 
			
		||||
        unsigned ebits = m_util.get_ebits(f->get_range());
 | 
			
		||||
        unsigned sbits = m_util.get_sbits(f->get_range());
 | 
			
		||||
| 
						 | 
				
			
			@ -2028,10 +2085,10 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a
 | 
			
		|||
        m_bv_util.is_numeral(to_expr(args[0]), tmp_rat, sz);
 | 
			
		||||
        SASSERT(tmp_rat.is_int32());
 | 
			
		||||
        SASSERT(sz == 3);
 | 
			
		||||
        BV_RM_VAL bv_rm = (BV_RM_VAL) tmp_rat.get_unsigned();
 | 
			
		||||
        BV_RM_VAL bv_rm = (BV_RM_VAL)tmp_rat.get_unsigned();
 | 
			
		||||
 | 
			
		||||
        mpf_rounding_mode rm;
 | 
			
		||||
        switch(bv_rm)
 | 
			
		||||
        switch (bv_rm)
 | 
			
		||||
        {
 | 
			
		||||
        case BV_RM_TIES_TO_AWAY: rm = MPF_ROUND_NEAREST_TAWAY; break;
 | 
			
		||||
        case BV_RM_TIES_TO_EVEN: rm = MPF_ROUND_NEAREST_TEVEN; break;
 | 
			
		||||
| 
						 | 
				
			
			@ -2044,20 +2101,21 @@ void fpa2bv_converter::mk_to_float(func_decl * f, unsigned num, expr * const * a
 | 
			
		|||
        SASSERT(m_util.au().is_numeral(args[1]));
 | 
			
		||||
 | 
			
		||||
        rational q;
 | 
			
		||||
        SASSERT(m_util.au().is_numeral(args[1]));
 | 
			
		||||
        m_util.au().is_numeral(args[1], q);
 | 
			
		||||
 | 
			
		||||
        mpf v;
 | 
			
		||||
        m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
 | 
			
		||||
 | 
			
		||||
        expr * sgn = m_bv_util.mk_numeral((m_util.fm().sgn(v)) ? 1 : 0, 1);
 | 
			
		||||
        expr * s = m_bv_util.mk_numeral(m_util.fm().sig(v), sbits-1);
 | 
			
		||||
        expr * s = m_bv_util.mk_numeral(m_util.fm().sig(v), sbits - 1);
 | 
			
		||||
        expr * e = m_bv_util.mk_numeral(m_util.fm().exp(v), ebits);
 | 
			
		||||
 | 
			
		||||
        mk_triple(sgn, s, e, result);
 | 
			
		||||
 | 
			
		||||
        m_util.fm().del(v);
 | 
			
		||||
    }
 | 
			
		||||
    else
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
 | 
			
		||||
    SASSERT(is_well_sorted(m, result));    
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,9 +45,10 @@ class fpa2bv_converter {
 | 
			
		|||
    ast_manager              & m;
 | 
			
		||||
    basic_simplifier_plugin    m_simp;
 | 
			
		||||
    float_util                 m_util;
 | 
			
		||||
    bv_util                    m_bv_util;
 | 
			
		||||
    arith_util                 m_arith_util;
 | 
			
		||||
    mpf_manager              & m_mpf_manager;
 | 
			
		||||
    unsynch_mpz_manager      & m_mpz_manager;    
 | 
			
		||||
    bv_util                    m_bv_util;    
 | 
			
		||||
    float_decl_plugin        * m_plugin;
 | 
			
		||||
 | 
			
		||||
    obj_map<func_decl, expr*>  m_const2bv;
 | 
			
		||||
| 
						 | 
				
			
			@ -64,8 +65,9 @@ public:
 | 
			
		|||
 | 
			
		||||
    bool is_float(sort * s) { return m_util.is_float(s); }
 | 
			
		||||
    bool is_float(expr * e) { return is_app(e) && m_util.is_float(to_app(e)->get_decl()->get_range()); }
 | 
			
		||||
    bool is_rm(expr * e) { return m_util.is_rm(e); }
 | 
			
		||||
    bool is_rm(sort * s) { return m_util.is_rm(s); }
 | 
			
		||||
    bool is_float_family(func_decl * f) { return f->get_family_id() == m_util.get_family_id(); }
 | 
			
		||||
    bool is_rm_sort(sort * s) { return m_util.is_rm(s); }
 | 
			
		||||
 | 
			
		||||
    void mk_triple(expr * sign, expr * significand, expr * exponent, expr_ref & result) {
 | 
			
		||||
        SASSERT(m_bv_util.is_bv(sign) && m_bv_util.get_bv_size(sign) == 1);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -76,17 +76,23 @@ struct fpa2bv_rewriter_cfg : public default_rewriter_cfg {
 | 
			
		|||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_rm_sort(f->get_range())) {
 | 
			
		||||
        if (num == 0 && f->get_family_id() == null_family_id && m_conv.is_rm(f->get_range())) {
 | 
			
		||||
            m_conv.mk_rm_const(f, result);
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (m().is_eq(f)) {
 | 
			
		||||
            SASSERT(num == 2);
 | 
			
		||||
            if (m_conv.is_float(args[0])) {
 | 
			
		||||
            SASSERT(m().get_sort(args[0]) == m().get_sort(args[1]));
 | 
			
		||||
            sort * ds = f->get_domain()[0];
 | 
			
		||||
            if (m_conv.is_float(ds)) {
 | 
			
		||||
                m_conv.mk_eq(args[0], args[1], result);
 | 
			
		||||
                return BR_DONE;
 | 
			
		||||
            }
 | 
			
		||||
            else if (m_conv.is_rm(ds)) {
 | 
			
		||||
                result = m().mk_eq(args[0], args[1]);
 | 
			
		||||
                return BR_DONE;
 | 
			
		||||
            }
 | 
			
		||||
            return BR_FAILED;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ void quasi_macros::find_occurrences(expr * e) {
 | 
			
		|||
 | 
			
		||||
    // we remember whether we have seen an expr once, or more than once;
 | 
			
		||||
    // when we see it the second time, we don't have to visit it another time,
 | 
			
		||||
    // as we are only intersted in finding unique function applications. 
 | 
			
		||||
    // as we are only interested in finding unique function applications. 
 | 
			
		||||
    m_visited_once.reset();
 | 
			
		||||
    m_visited_more.reset();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +61,7 @@ void quasi_macros::find_occurrences(expr * e) {
 | 
			
		|||
            case AST_VAR: break;
 | 
			
		||||
            case AST_QUANTIFIER: m_todo.push_back(to_quantifier(cur)->get_expr()); break;
 | 
			
		||||
            case AST_APP:
 | 
			
		||||
                if (is_uninterp(cur) && !is_ground(cur)) {
 | 
			
		||||
                if (is_non_ground_uninterp(cur)) {
 | 
			
		||||
                    func_decl * f = to_app(cur)->get_decl();
 | 
			
		||||
                    m_occurrences.insert_if_not_there(f, 0);
 | 
			
		||||
                    occurrences_map::iterator it = m_occurrences.find_iterator(f);                    
 | 
			
		||||
| 
						 | 
				
			
			@ -76,6 +76,10 @@ void quasi_macros::find_occurrences(expr * e) {
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool quasi_macros::is_non_ground_uninterp(expr const * e) const {
 | 
			
		||||
    return is_non_ground(e) && is_uninterp(e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool quasi_macros::is_unique(func_decl * f) const {
 | 
			
		||||
    return m_occurrences.find(f) == 1;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -149,6 +153,7 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
 | 
			
		|||
    // Our definition of a quasi-macro:
 | 
			
		||||
    // Forall X. f[X] = T[X], where f[X] is a term starting with symbol f, f is uninterpreted, 
 | 
			
		||||
    // f[X] contains all universally quantified variables, and f does not occur in T[X].
 | 
			
		||||
    TRACE("quasi_macros", tout << "Checking for quasi macro: " << mk_pp(e, m_manager) << std::endl;);
 | 
			
		||||
 | 
			
		||||
    if (is_quantifier(e) && to_quantifier(e)->is_forall()) {
 | 
			
		||||
        quantifier * q = to_quantifier(e);
 | 
			
		||||
| 
						 | 
				
			
			@ -157,23 +162,23 @@ bool quasi_macros::is_quasi_macro(expr * e, app_ref & a, expr_ref & t) const {
 | 
			
		|||
            expr * lhs = to_app(qe)->get_arg(0);
 | 
			
		||||
            expr * rhs = to_app(qe)->get_arg(1);
 | 
			
		||||
 | 
			
		||||
            if (is_uninterp(lhs) && is_unique(to_app(lhs)->get_decl()) && 
 | 
			
		||||
            if (is_non_ground_uninterp(lhs) && is_unique(to_app(lhs)->get_decl()) &&
 | 
			
		||||
                !depends_on(rhs, to_app(lhs)->get_decl()) && fully_depends_on(to_app(lhs), q)) {
 | 
			
		||||
                a = to_app(lhs);
 | 
			
		||||
                t = rhs;                
 | 
			
		||||
                return true;
 | 
			
		||||
            } else if (is_uninterp(rhs) && is_unique(to_app(rhs)->get_decl()) && 
 | 
			
		||||
            } else if (is_non_ground_uninterp(rhs) && is_unique(to_app(rhs)->get_decl()) &&
 | 
			
		||||
                !depends_on(lhs, to_app(rhs)->get_decl()) && fully_depends_on(to_app(rhs), q)) {                
 | 
			
		||||
                a = to_app(rhs);
 | 
			
		||||
                t = lhs;                
 | 
			
		||||
                return true;
 | 
			
		||||
            }            
 | 
			
		||||
        } else if (m_manager.is_not(qe) && is_uninterp(to_app(qe)->get_arg(0)) &&
 | 
			
		||||
        } else if (m_manager.is_not(qe) && is_non_ground_uninterp(to_app(qe)->get_arg(0)) &&
 | 
			
		||||
                   is_unique(to_app(to_app(qe)->get_arg(0))->get_decl())) { // this is like f(...) = false
 | 
			
		||||
            a = to_app(to_app(qe)->get_arg(0));
 | 
			
		||||
            t = m_manager.mk_false();
 | 
			
		||||
            return true;
 | 
			
		||||
        } else if (is_uninterp(qe) && is_unique(to_app(qe)->get_decl())) { // this is like f(...) = true
 | 
			
		||||
        } else if (is_non_ground_uninterp(qe) && is_unique(to_app(qe)->get_decl())) { // this is like f(...) = true
 | 
			
		||||
            a = to_app(qe);
 | 
			
		||||
            t = m_manager.mk_true();
 | 
			
		||||
            return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -45,6 +45,7 @@ class quasi_macros {
 | 
			
		|||
    expr_mark                 m_visited_more;
 | 
			
		||||
    
 | 
			
		||||
    bool is_unique(func_decl * f) const;
 | 
			
		||||
    bool is_non_ground_uninterp(expr const * e) const;
 | 
			
		||||
    bool fully_depends_on(app * a, quantifier * q) const;    
 | 
			
		||||
    bool depends_on(expr * e, func_decl * f) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -82,7 +82,7 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
 | 
			
		||||
    if (num_args == 2) {
 | 
			
		||||
        mpf_rounding_mode rm;
 | 
			
		||||
        if (!m_util.is_rm(args[0], rm))
 | 
			
		||||
        if (!m_util.is_rm_value(args[0], rm))
 | 
			
		||||
            return BR_FAILED;
 | 
			
		||||
        
 | 
			
		||||
        rational q;
 | 
			
		||||
| 
						 | 
				
			
			@ -109,12 +109,12 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
            return BR_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
    else if (num_args == 3 && 
 | 
			
		||||
             m_util.is_rm(m().get_sort(args[0])) && 
 | 
			
		||||
             m_util.is_rm(args[0]) && 
 | 
			
		||||
             m_util.au().is_real(args[1]) &&
 | 
			
		||||
             m_util.au().is_int(args[2])) {
 | 
			
		||||
 | 
			
		||||
        mpf_rounding_mode rm;
 | 
			
		||||
        if (!m_util.is_rm(args[0], rm))
 | 
			
		||||
        if (!m_util.is_rm_value(args[0], rm))
 | 
			
		||||
            return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
        rational q;
 | 
			
		||||
| 
						 | 
				
			
			@ -130,7 +130,6 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
	    m_util.fm().set(v, ebits, sbits, rm, q.to_mpq(), e.to_mpq().numerator());
 | 
			
		||||
        result = m_util.mk_value(v);
 | 
			
		||||
        m_util.fm().del(v);
 | 
			
		||||
        // TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +139,7 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
 | 
			
		||||
br_status float_rewriter::mk_add(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {    
 | 
			
		||||
    mpf_rounding_mode rm;
 | 
			
		||||
    if (m_util.is_rm(arg1, rm)) {
 | 
			
		||||
    if (m_util.is_rm_value(arg1, rm)) {
 | 
			
		||||
        scoped_mpf v2(m_util.fm()), v3(m_util.fm());
 | 
			
		||||
        if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
 | 
			
		||||
            scoped_mpf t(m_util.fm());
 | 
			
		||||
| 
						 | 
				
			
			@ -161,7 +160,7 @@ br_status float_rewriter::mk_sub(expr * arg1, expr * arg2, expr * arg3, expr_ref
 | 
			
		|||
 | 
			
		||||
br_status float_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {    
 | 
			
		||||
    mpf_rounding_mode rm;
 | 
			
		||||
    if (m_util.is_rm(arg1, rm)) {
 | 
			
		||||
    if (m_util.is_rm_value(arg1, rm)) {
 | 
			
		||||
        scoped_mpf v2(m_util.fm()), v3(m_util.fm());
 | 
			
		||||
        if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
 | 
			
		||||
            scoped_mpf t(m_util.fm());
 | 
			
		||||
| 
						 | 
				
			
			@ -176,7 +175,7 @@ br_status float_rewriter::mk_mul(expr * arg1, expr * arg2, expr * arg3, expr_ref
 | 
			
		|||
 | 
			
		||||
br_status float_rewriter::mk_div(expr * arg1, expr * arg2, expr * arg3, expr_ref & result) {
 | 
			
		||||
    mpf_rounding_mode rm;
 | 
			
		||||
    if (m_util.is_rm(arg1, rm)) {
 | 
			
		||||
    if (m_util.is_rm_value(arg1, rm)) {
 | 
			
		||||
        scoped_mpf v2(m_util.fm()), v3(m_util.fm());
 | 
			
		||||
        if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3)) {
 | 
			
		||||
            scoped_mpf t(m_util.fm());
 | 
			
		||||
| 
						 | 
				
			
			@ -287,7 +286,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		|||
 | 
			
		||||
br_status float_rewriter::mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4, expr_ref & result) {
 | 
			
		||||
    mpf_rounding_mode rm;
 | 
			
		||||
    if (m_util.is_rm(arg1, rm)) {
 | 
			
		||||
    if (m_util.is_rm_value(arg1, rm)) {
 | 
			
		||||
        scoped_mpf v2(m_util.fm()), v3(m_util.fm()), v4(m_util.fm());
 | 
			
		||||
        if (m_util.is_value(arg2, v2) && m_util.is_value(arg3, v3) && m_util.is_value(arg4, v4)) {
 | 
			
		||||
            scoped_mpf t(m_util.fm());
 | 
			
		||||
| 
						 | 
				
			
			@ -302,7 +301,7 @@ br_status float_rewriter::mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, exp
 | 
			
		|||
 | 
			
		||||
br_status float_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		||||
    mpf_rounding_mode rm;
 | 
			
		||||
    if (m_util.is_rm(arg1, rm)) {
 | 
			
		||||
    if (m_util.is_rm_value(arg1, rm)) {
 | 
			
		||||
        scoped_mpf v2(m_util.fm());
 | 
			
		||||
        if (m_util.is_value(arg2, v2)) {
 | 
			
		||||
            scoped_mpf t(m_util.fm());
 | 
			
		||||
| 
						 | 
				
			
			@ -317,7 +316,7 @@ br_status float_rewriter::mk_sqrt(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		|||
 | 
			
		||||
br_status float_rewriter::mk_round(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		||||
    mpf_rounding_mode rm;
 | 
			
		||||
    if (m_util.is_rm(arg1, rm)) {
 | 
			
		||||
    if (m_util.is_rm_value(arg1, rm)) {
 | 
			
		||||
        scoped_mpf v2(m_util.fm());
 | 
			
		||||
        if (m_util.is_value(arg2, v2)) {
 | 
			
		||||
            scoped_mpf t(m_util.fm());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -547,6 +547,9 @@ public:
 | 
			
		|||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#define STRINGIZE(x) #x
 | 
			
		||||
#define STRINGIZE_VALUE_OF(x) STRINGIZE(x)
 | 
			
		||||
 | 
			
		||||
class get_info_cmd : public cmd {
 | 
			
		||||
    symbol   m_error_behavior;
 | 
			
		||||
    symbol   m_name;
 | 
			
		||||
| 
						 | 
				
			
			@ -584,7 +587,11 @@ public:
 | 
			
		|||
            ctx.regular_stream() << "(:authors \"Leonardo de Moura and Nikolaj Bjorner\")" << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
        else if (opt == m_version) {
 | 
			
		||||
            ctx.regular_stream() << "(:version \"" << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER << "\")" << std::endl;
 | 
			
		||||
            ctx.regular_stream() << "(:version \"" << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER
 | 
			
		||||
#ifdef Z3GITHASH
 | 
			
		||||
                << " - build hashcode " << STRINGIZE_VALUE_OF(Z3GITHASH)
 | 
			
		||||
#endif
 | 
			
		||||
                << "\")" << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
        else if (opt == m_status) {
 | 
			
		||||
            ctx.regular_stream() << "(:status " << ctx.get_status() << ")" << std::endl;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -978,13 +978,14 @@ namespace datalog {
 | 
			
		|||
        }        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void rule::get_vars(ptr_vector<sort>& sorts) const {
 | 
			
		||||
    void rule::get_vars(ast_manager& m, ptr_vector<sort>& sorts) const {
 | 
			
		||||
        sorts.reset();
 | 
			
		||||
        used_vars used;
 | 
			
		||||
        get_used_vars(used);
 | 
			
		||||
        unsigned sz = used.get_max_found_var_idx_plus_1();
 | 
			
		||||
        for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
            sorts.push_back(used.get(i));
 | 
			
		||||
            sort* s = used.get(i);
 | 
			
		||||
            sorts.push_back(s?s:m.mk_bool_sort());
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -304,7 +304,7 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
        void norm_vars(rule_manager & rm);
 | 
			
		||||
 | 
			
		||||
        void get_vars(ptr_vector<sort>& sorts) const;
 | 
			
		||||
        void get_vars(ast_manager& m, ptr_vector<sort>& sorts) const;
 | 
			
		||||
 | 
			
		||||
        void to_formula(expr_ref& result) const;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -290,7 +290,7 @@ namespace datalog {
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
            TRACE("dl_dr", 
 | 
			
		||||
                  tout << r.get_decl()->get_name() << "\n";
 | 
			
		||||
                  tout << mk_pp(r.get_head(), m) << " :- \n";
 | 
			
		||||
                  for (unsigned i = 0; i < body.size(); ++i) {
 | 
			
		||||
                      tout << mk_pp(body[i].get(), m) << "\n";
 | 
			
		||||
                  });
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ namespace datalog {
 | 
			
		|||
        
 | 
			
		||||
        void mk_qrule_vars(datalog::rule const& r, unsigned rule_id, expr_ref_vector& sub) {
 | 
			
		||||
            ptr_vector<sort> sorts;
 | 
			
		||||
            r.get_vars(sorts);
 | 
			
		||||
            r.get_vars(m, sorts);
 | 
			
		||||
            // populate substitution of bound variables.
 | 
			
		||||
            sub.reset();
 | 
			
		||||
            sub.resize(sorts.size());
 | 
			
		||||
| 
						 | 
				
			
			@ -421,7 +421,7 @@ namespace datalog {
 | 
			
		|||
                    ptr_vector<sort> rule_vars;
 | 
			
		||||
                    expr_ref_vector args(m), conjs(m);
 | 
			
		||||
 | 
			
		||||
                    r.get_vars(rule_vars);
 | 
			
		||||
                    r.get_vars(m, rule_vars);
 | 
			
		||||
                    obj_hashtable<expr> used_vars;
 | 
			
		||||
                    unsigned num_vars = 0;
 | 
			
		||||
                    for (unsigned i = 0; i < r.get_decl()->get_arity(); ++i) {
 | 
			
		||||
| 
						 | 
				
			
			@ -514,7 +514,7 @@ namespace datalog {
 | 
			
		|||
            unsigned sz = r->get_uninterpreted_tail_size();
 | 
			
		||||
 | 
			
		||||
            ptr_vector<sort> rule_vars;
 | 
			
		||||
            r->get_vars(rule_vars);
 | 
			
		||||
            r->get_vars(m, rule_vars);
 | 
			
		||||
            args.append(prop->get_num_args(), prop->get_args());
 | 
			
		||||
            expr_ref_vector sub = mk_skolem_binding(*r, rule_vars, args);
 | 
			
		||||
            if (sub.empty() && sz == 0) {
 | 
			
		||||
| 
						 | 
				
			
			@ -803,7 +803,7 @@ namespace datalog {
 | 
			
		|||
            func_decl* p = r.get_decl();
 | 
			
		||||
            ptr_vector<func_decl> const& succs  = *dtu.get_datatype_constructors(m.get_sort(path));
 | 
			
		||||
            // populate substitution of bound variables.
 | 
			
		||||
            r.get_vars(sorts);
 | 
			
		||||
            r.get_vars(m, sorts);
 | 
			
		||||
            sub.reset();
 | 
			
		||||
            sub.resize(sorts.size());
 | 
			
		||||
            for (unsigned k = 0; k < r.get_decl()->get_arity(); ++k) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1327,7 +1327,7 @@ namespace datalog {
 | 
			
		|||
        
 | 
			
		||||
        void mk_rule_vars(rule& r, unsigned level, unsigned rule_id, expr_ref_vector& sub) {
 | 
			
		||||
            ptr_vector<sort> sorts;
 | 
			
		||||
            r.get_vars(sorts);
 | 
			
		||||
            r.get_vars(m, sorts);
 | 
			
		||||
            // populate substitution of bound variables.
 | 
			
		||||
            sub.reset();
 | 
			
		||||
            sub.resize(sorts.size());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -87,7 +87,7 @@ namespace datalog {
 | 
			
		|||
        else {
 | 
			
		||||
            if (m_next_var == 0) {
 | 
			
		||||
                ptr_vector<sort> vars;
 | 
			
		||||
                r.get_vars(vars);
 | 
			
		||||
                r.get_vars(m, vars);
 | 
			
		||||
                m_next_var = vars.size() + 1;
 | 
			
		||||
            }
 | 
			
		||||
            v = m.mk_var(m_next_var, m.get_sort(e));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ Revision History:
 | 
			
		|||
#include "dl_mk_interp_tail_simplifier.h"
 | 
			
		||||
#include "fixedpoint_params.hpp"
 | 
			
		||||
#include "scoped_proof.h"
 | 
			
		||||
#include "model_v2_pp.h"
 | 
			
		||||
 | 
			
		||||
namespace datalog {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -67,11 +68,17 @@ namespace datalog {
 | 
			
		|||
                func_decl* p = m_new_funcs[i].get();
 | 
			
		||||
                func_decl* q = m_old_funcs[i].get();
 | 
			
		||||
                func_interp* f = model->get_func_interp(p);
 | 
			
		||||
                if (!f) continue;
 | 
			
		||||
                expr_ref body(m);                
 | 
			
		||||
                unsigned arity_p = p->get_arity();
 | 
			
		||||
                unsigned arity_q = q->get_arity();
 | 
			
		||||
                TRACE("dl",
 | 
			
		||||
                      model_v2_pp(tout, *model);
 | 
			
		||||
                      tout << mk_pp(p, m) << "\n";
 | 
			
		||||
                      tout << mk_pp(q, m) << "\n";);
 | 
			
		||||
                SASSERT(0 < arity_p);
 | 
			
		||||
                model->register_decl(p, f);
 | 
			
		||||
                SASSERT(f);
 | 
			
		||||
                model->register_decl(p, f->copy());
 | 
			
		||||
                func_interp* g = alloc(func_interp, m, arity_q);
 | 
			
		||||
 | 
			
		||||
                if (f) {
 | 
			
		||||
| 
						 | 
				
			
			@ -88,11 +95,12 @@ namespace datalog {
 | 
			
		|||
                for (unsigned j = 0; j < arity_q; ++j) {
 | 
			
		||||
                    sort* s = q->get_domain(j);
 | 
			
		||||
                    arg = m.mk_var(j, s);
 | 
			
		||||
                    expr* t = arg;
 | 
			
		||||
                    if (m_bv.is_bv_sort(s)) {
 | 
			
		||||
                        expr* args[1] = { arg };
 | 
			
		||||
                        unsigned sz = m_bv.get_bv_size(s);
 | 
			
		||||
                        for (unsigned k = 0; k < sz; ++k) {
 | 
			
		||||
                            proj = m.mk_app(m_bv.get_family_id(), OP_BIT2BOOL, 1, args);
 | 
			
		||||
                            parameter p(k);
 | 
			
		||||
                            proj = m.mk_app(m_bv.get_family_id(), OP_BIT2BOOL, 1, &p, 1, &t);
 | 
			
		||||
                            sub.insert(m.mk_var(idx++, m.mk_bool_sort()), proj); 
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,7 +62,7 @@ namespace datalog {
 | 
			
		|||
        rule_ref r(const_cast<rule*>(&rl), rm);
 | 
			
		||||
        ptr_vector<sort> sorts;
 | 
			
		||||
        expr_ref_vector revsub(m), conjs(m);
 | 
			
		||||
        rl.get_vars(sorts);
 | 
			
		||||
        rl.get_vars(m, sorts);
 | 
			
		||||
        revsub.resize(sorts.size());  
 | 
			
		||||
        svector<bool> valid(sorts.size(), true);
 | 
			
		||||
        for (unsigned i = 0; i < sub.size(); ++i) {
 | 
			
		||||
| 
						 | 
				
			
			@ -117,8 +117,8 @@ namespace datalog {
 | 
			
		|||
        rule_ref res(rm);
 | 
			
		||||
        bool_rewriter bwr(m);
 | 
			
		||||
        svector<bool> is_neg;
 | 
			
		||||
        tgt->get_vars(sorts1);
 | 
			
		||||
        src.get_vars(sorts2);
 | 
			
		||||
        tgt->get_vars(m, sorts1);
 | 
			
		||||
        src.get_vars(m, sorts2);
 | 
			
		||||
 | 
			
		||||
        mk_pred(head, src.get_head(), tgt->get_head()); 
 | 
			
		||||
        for (unsigned i = 0; i < src.get_uninterpreted_tail_size(); ++i) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -199,7 +199,7 @@ namespace datalog {
 | 
			
		|||
        expr_ref fml(m), cnst(m);
 | 
			
		||||
        var_ref var(m);
 | 
			
		||||
        ptr_vector<sort> sorts;
 | 
			
		||||
        r.get_vars(sorts);
 | 
			
		||||
        r.get_vars(m, sorts);
 | 
			
		||||
        m_uf.reset();
 | 
			
		||||
        m_terms.reset();
 | 
			
		||||
        m_var2cnst.reset();
 | 
			
		||||
| 
						 | 
				
			
			@ -207,9 +207,6 @@ namespace datalog {
 | 
			
		|||
        fml = m.mk_and(conjs.size(), conjs.c_ptr());
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < sorts.size(); ++i) {
 | 
			
		||||
            if (!sorts[i]) {
 | 
			
		||||
                sorts[i] = m.mk_bool_sort();
 | 
			
		||||
            }
 | 
			
		||||
            var = m.mk_var(i, sorts[i]);
 | 
			
		||||
            cnst = m.mk_fresh_const("C", sorts[i]);
 | 
			
		||||
            m_var2cnst.insert(var, cnst);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -143,11 +143,8 @@ namespace datalog {
 | 
			
		|||
        expr_ref_vector result(m);
 | 
			
		||||
        ptr_vector<sort> sorts;
 | 
			
		||||
        expr_ref v(m), w(m);
 | 
			
		||||
        r.get_vars(sorts);
 | 
			
		||||
        r.get_vars(m, sorts);
 | 
			
		||||
        for (unsigned i = 0; i < sorts.size(); ++i) {
 | 
			
		||||
            if (!sorts[i]) {
 | 
			
		||||
                sorts[i] = m.mk_bool_sort();
 | 
			
		||||
            }
 | 
			
		||||
            v = m.mk_var(i, sorts[i]);
 | 
			
		||||
            m_subst.apply(2, m_deltas, expr_offset(v, is_tgt?0:1), w);
 | 
			
		||||
            result.push_back(w);            
 | 
			
		||||
| 
						 | 
				
			
			@ -423,6 +420,11 @@ namespace datalog {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        TRACE("dl", tout << "inlined rules after mutual inlining:\n" << m_inlined_rules;  );
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < m_inlined_rules.get_num_rules(); ++i) {
 | 
			
		||||
            rule* r = m_inlined_rules.get_rule(i);
 | 
			
		||||
            datalog::del_rule(m_mc, *r);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool mk_rule_inliner::transform_rule(rule_set const& orig, rule * r0, rule_set& tgt) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -141,7 +141,7 @@ namespace datalog {
 | 
			
		|||
            m_cache.reset();
 | 
			
		||||
            m_trail.reset();
 | 
			
		||||
            m_eqs.reset();
 | 
			
		||||
            r.get_vars(vars);
 | 
			
		||||
            r.get_vars(m, vars);
 | 
			
		||||
            unsigned num_vars = vars.size();
 | 
			
		||||
            for (unsigned j = 0; j < utsz; ++j) {
 | 
			
		||||
                tail.push_back(mk_pred(num_vars, r.get_tail(j)));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										109
									
								
								src/qe/qe.cpp
									
										
									
									
									
								
							
							
						
						
									
										109
									
								
								src/qe/qe.cpp
									
										
									
									
									
								
							| 
						 | 
				
			
			@ -1120,6 +1120,7 @@ namespace qe {
 | 
			
		|||
            st->init(fml);
 | 
			
		||||
            st->m_vars.append(m_vars.size(), m_vars.c_ptr());
 | 
			
		||||
            SASSERT(invariant());
 | 
			
		||||
            TRACE("qe", tout << mk_pp(m_fml, m) << " child: " << mk_pp(fml, m) << "\n";);
 | 
			
		||||
            return st;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1133,6 +1134,7 @@ namespace qe {
 | 
			
		|||
            m_branch_index.insert(branch_id, index);
 | 
			
		||||
            st->m_vars.append(m_vars.size(), m_vars.c_ptr());
 | 
			
		||||
            SASSERT(invariant());
 | 
			
		||||
            //TRACE("qe", tout << mk_pp(m_fml, m) << " child: " << mk_pp(st->fml(), m) << "\n";);
 | 
			
		||||
            return st;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1164,6 +1166,16 @@ namespace qe {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        expr_ref abstract_variable(app* x, expr* fml) const {
 | 
			
		||||
            expr_ref result(m);
 | 
			
		||||
            expr* y = x;
 | 
			
		||||
            expr_abstract(m, 0, 1, &y, fml, result);            
 | 
			
		||||
            symbol X(x->get_decl()->get_name());
 | 
			
		||||
            sort* s = m.get_sort(x);
 | 
			
		||||
            result = m.mk_exists(1, &s, &X, result);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void display_validate(std::ostream& out) const {
 | 
			
		||||
            if (m_children.empty()) {
 | 
			
		||||
                return;
 | 
			
		||||
| 
						 | 
				
			
			@ -1171,25 +1183,53 @@ namespace qe {
 | 
			
		|||
            expr_ref q(m);
 | 
			
		||||
            expr* x = m_var;
 | 
			
		||||
            if (x) {
 | 
			
		||||
                expr_abstract(m, 0, 1, &x, m_fml, q);
 | 
			
		||||
                ptr_vector<expr> fmls;
 | 
			
		||||
                q = abstract_variable(m_var, m_fml);
 | 
			
		||||
 | 
			
		||||
                expr_ref_vector fmls(m);
 | 
			
		||||
                expr_ref fml(m);
 | 
			
		||||
                for (unsigned i = 0; i < m_children.size(); ++i) {
 | 
			
		||||
                    expr* fml = m_children[i]->fml();
 | 
			
		||||
                    search_tree const& child = *m_children[i];
 | 
			
		||||
                    fml = child.fml();
 | 
			
		||||
                    if (fml) {
 | 
			
		||||
                        // abstract free variables in children.
 | 
			
		||||
                        ptr_vector<app> child_vars, new_vars;
 | 
			
		||||
                        child_vars.append(child.m_vars.size(), child.m_vars.c_ptr());
 | 
			
		||||
                        if (child.m_var) {
 | 
			
		||||
                            child_vars.push_back(child.m_var);
 | 
			
		||||
                        }
 | 
			
		||||
                        for (unsigned j = 0; j < child_vars.size(); ++j) {
 | 
			
		||||
                            if (!m_vars.contains(child_vars[j]) &&
 | 
			
		||||
                                !new_vars.contains(child_vars[j])) {
 | 
			
		||||
                                fml = abstract_variable(child_vars[j], fml);
 | 
			
		||||
                                new_vars.push_back(child_vars[j]);
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        fmls.push_back(fml);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                symbol X(m_var->get_decl()->get_name());
 | 
			
		||||
                sort* s = m.get_sort(x);
 | 
			
		||||
                q = m.mk_exists(1, &s, &X, q);
 | 
			
		||||
                expr_ref tmp(m);
 | 
			
		||||
                bool_rewriter(m).mk_or(fmls.size(), fmls.c_ptr(), tmp);
 | 
			
		||||
                expr_ref f(m.mk_not(m.mk_iff(q, tmp)), m);
 | 
			
		||||
                bool_rewriter(m).mk_or(fmls.size(), fmls.c_ptr(), fml);
 | 
			
		||||
                
 | 
			
		||||
                fml = m.mk_not(m.mk_iff(q, fml));
 | 
			
		||||
                ast_smt_pp pp(m);
 | 
			
		||||
                out << "(echo " << m_var->get_decl()->get_name() << ")\n";
 | 
			
		||||
                out << "; eliminate " << mk_pp(m_var, m) << "\n";
 | 
			
		||||
                out << "(push)\n";
 | 
			
		||||
                pp.display_smt2(out, f);
 | 
			
		||||
                pp.display_smt2(out, fml);                
 | 
			
		||||
                out << "(pop)\n\n";      
 | 
			
		||||
                DEBUG_CODE(
 | 
			
		||||
                    smt_params params;
 | 
			
		||||
                    params.m_simplify_bit2int = true;
 | 
			
		||||
                    params.m_arith_enum_const_mod = true;
 | 
			
		||||
                    params.m_bv_enable_int2bv2int = true;
 | 
			
		||||
                    params.m_relevancy_lvl = 0;
 | 
			
		||||
                    smt::kernel ctx(m, params);
 | 
			
		||||
                    ctx.assert_expr(fml);
 | 
			
		||||
                    lbool is_sat = ctx.check();
 | 
			
		||||
                    if (is_sat == l_true) {
 | 
			
		||||
                        std::cout << "; Validation failed:\n";
 | 
			
		||||
                        std::cout << mk_pp(fml, m) << "\n";
 | 
			
		||||
                    }
 | 
			
		||||
);
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
            for (unsigned i = 0; i < m_children.size(); ++i) {
 | 
			
		||||
                if (m_children[i]->fml()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1410,13 +1450,9 @@ namespace qe {
 | 
			
		|||
            m_solver.assert_expr(m_fml);
 | 
			
		||||
            if (assumption) m_solver.assert_expr(assumption);
 | 
			
		||||
            bool is_sat = false;            
 | 
			
		||||
            while (l_false != m_solver.check()) {
 | 
			
		||||
            while (l_true == m_solver.check()) {
 | 
			
		||||
                is_sat = true;
 | 
			
		||||
                model_ref model;
 | 
			
		||||
                m_solver.get_model(model);
 | 
			
		||||
                TRACE("qe", model_v2_pp(tout, *model););
 | 
			
		||||
                model_evaluator model_eval(*model);
 | 
			
		||||
                final_check(model_eval);
 | 
			
		||||
                final_check();
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (!is_sat) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1466,14 +1502,30 @@ namespace qe {
 | 
			
		|||
 | 
			
		||||
    private:
 | 
			
		||||
 | 
			
		||||
        void final_check(model_evaluator& model_eval) {
 | 
			
		||||
            TRACE("qe", tout << "\n";);
 | 
			
		||||
            while (can_propagate_assignment(model_eval)) {
 | 
			
		||||
                propagate_assignment(model_eval);
 | 
			
		||||
        void final_check() {
 | 
			
		||||
            model_ref model;
 | 
			
		||||
            m_solver.get_model(model);
 | 
			
		||||
            scoped_ptr<model_evaluator> model_eval = alloc(model_evaluator, *model);
 | 
			
		||||
 | 
			
		||||
            while (true) {
 | 
			
		||||
                TRACE("qe", model_v2_pp(tout, *model););
 | 
			
		||||
                while (can_propagate_assignment(*model_eval)) {
 | 
			
		||||
                    propagate_assignment(*model_eval);
 | 
			
		||||
                }
 | 
			
		||||
            VERIFY(CHOOSE_VAR == update_current(model_eval, true));
 | 
			
		||||
                VERIFY(CHOOSE_VAR == update_current(*model_eval, true));
 | 
			
		||||
                SASSERT(m_current->fml());
 | 
			
		||||
            pop(model_eval);        
 | 
			
		||||
                if (l_true != m_solver.check()) {
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
                m_solver.get_model(model);
 | 
			
		||||
                model_eval = alloc(model_evaluator, *model);
 | 
			
		||||
                search_tree* st = m_current;
 | 
			
		||||
                update_current(*model_eval, false);
 | 
			
		||||
                if (st == m_current) {
 | 
			
		||||
                    break;
 | 
			
		||||
                }
 | 
			
		||||
            }            
 | 
			
		||||
            pop(*model_eval);                    
 | 
			
		||||
        } 
 | 
			
		||||
 | 
			
		||||
        ast_manager& get_manager() { return m; }
 | 
			
		||||
| 
						 | 
				
			
			@ -1633,6 +1685,7 @@ namespace qe {
 | 
			
		|||
                nb = m_current->get_num_branches();
 | 
			
		||||
                expr_ref fml(m_current->fml(), m);
 | 
			
		||||
                if (!eval(model_eval, b, branch) || branch >= nb) {
 | 
			
		||||
                    TRACE("qe", tout << "evaluation failed: setting branch to 0\n";);
 | 
			
		||||
                    branch = rational::zero();
 | 
			
		||||
                }
 | 
			
		||||
                SASSERT(!branch.is_neg());
 | 
			
		||||
| 
						 | 
				
			
			@ -1694,11 +1747,12 @@ namespace qe {
 | 
			
		|||
            }
 | 
			
		||||
 | 
			
		||||
            //
 | 
			
		||||
            // The current state is satisfiable
 | 
			
		||||
            // and the closed portion of the formula
 | 
			
		||||
            // can be used as the quantifier-free portion.
 | 
			
		||||
            // The closed portion of the formula
 | 
			
		||||
            // can be used as the quantifier-free portion, 
 | 
			
		||||
            // unless the current state is unsatisfiable.
 | 
			
		||||
            // 
 | 
			
		||||
            if (m.is_true(fml_mixed)) {
 | 
			
		||||
                SASSERT(l_true == m_solver.check());
 | 
			
		||||
                m_current = m_current->add_child(fml_closed);
 | 
			
		||||
                for (unsigned i = 0; m_defs && i < m_current->num_free_vars(); ++i) {
 | 
			
		||||
                    expr_ref val(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -1708,6 +1762,7 @@ namespace qe {
 | 
			
		|||
                    if (val == x) {
 | 
			
		||||
                        model_ref model;
 | 
			
		||||
                        lbool is_sat = m_solver.check();
 | 
			
		||||
                        if (is_sat == l_undef) return;
 | 
			
		||||
                        m_solver.get_model(model);
 | 
			
		||||
                        SASSERT(is_sat == l_true);
 | 
			
		||||
                        model_evaluator model_eval2(*model);
 | 
			
		||||
| 
						 | 
				
			
			@ -1890,7 +1945,7 @@ namespace qe {
 | 
			
		|||
                vars.reset();
 | 
			
		||||
                closed = closed && (r != l_undef);
 | 
			
		||||
            }        
 | 
			
		||||
            TRACE("qe", tout << mk_ismt2_pp(fml, m) << "\n";);
 | 
			
		||||
            TRACE("qe", tout << mk_pp(fml, m) << "\n";);
 | 
			
		||||
            m_current->add_child(fml)->reset_free_vars();
 | 
			
		||||
            block_assignment(); 
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,6 +31,7 @@ Revision History:
 | 
			
		|||
#include "obj_pair_hashtable.h"
 | 
			
		||||
#include "nlarith_util.h"
 | 
			
		||||
#include "model_evaluator.h"
 | 
			
		||||
#include "smt_kernel.h"
 | 
			
		||||
 | 
			
		||||
namespace qe {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -81,8 +82,8 @@ namespace qe {
 | 
			
		|||
        i_solver_context& m_ctx;
 | 
			
		||||
    public:
 | 
			
		||||
        arith_util        m_arith; // initialize before m_zero_i, etc.
 | 
			
		||||
        th_rewriter       simplify;
 | 
			
		||||
    private:
 | 
			
		||||
        th_rewriter       m_rewriter;
 | 
			
		||||
        arith_eq_solver   m_arith_solver;
 | 
			
		||||
        bv_util           m_bv;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +103,7 @@ namespace qe {
 | 
			
		|||
            m(m), 
 | 
			
		||||
            m_ctx(ctx),
 | 
			
		||||
            m_arith(m),
 | 
			
		||||
            m_rewriter(m),
 | 
			
		||||
            simplify(m),
 | 
			
		||||
            m_arith_solver(m),
 | 
			
		||||
            m_bv(m),
 | 
			
		||||
            m_zero_i(m_arith.mk_numeral(numeral(0), true), m),
 | 
			
		||||
| 
						 | 
				
			
			@ -434,7 +435,6 @@ namespace qe {
 | 
			
		|||
            expr_ref tmp(e, m);
 | 
			
		||||
            simplify(tmp);
 | 
			
		||||
            m_arith_rewriter.mk_le(tmp, mk_zero(e), result);
 | 
			
		||||
            TRACE("qe_verbose", tout << "mk_le " << mk_pp(result, m) << "\n";);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void mk_lt(expr* e, expr_ref& result) {
 | 
			
		||||
| 
						 | 
				
			
			@ -521,7 +521,8 @@ namespace qe {
 | 
			
		|||
                expr_ref result1(m), result2(m);
 | 
			
		||||
                
 | 
			
		||||
                // a*s + b*t <= 0
 | 
			
		||||
                expr_ref as_bt_le_0(result, m), tmp2(m), tmp3(m), tmp4(m);
 | 
			
		||||
                expr_ref as_bt_le_0(result, m), tmp2(m), asz_bt_le_0(m), tmp3(m), tmp4(m);
 | 
			
		||||
                expr_ref b_divides_sz(m);
 | 
			
		||||
                
 | 
			
		||||
                // a*s + b*t + (a-1)(b-1) <= 0
 | 
			
		||||
                tmp2 = m_arith.mk_add(as_bt, slack);
 | 
			
		||||
| 
						 | 
				
			
			@ -560,30 +561,36 @@ namespace qe {
 | 
			
		|||
                    sz = m_arith.mk_uminus(sz);
 | 
			
		||||
                }
 | 
			
		||||
                tmp4 = mk_add(mk_mul(a1, sz), bt);
 | 
			
		||||
                mk_le(tmp4, tmp3);
 | 
			
		||||
                mk_le(tmp4, asz_bt_le_0);
 | 
			
		||||
 | 
			
		||||
                if (to_app(tmp3)->get_arg(0) == x &&
 | 
			
		||||
                    m_arith.is_zero(to_app(tmp3)->get_arg(1))) {
 | 
			
		||||
                if (to_app(asz_bt_le_0)->get_arg(0) == x &&
 | 
			
		||||
                    m_arith.is_zero(to_app(asz_bt_le_0)->get_arg(1))) {
 | 
			
		||||
                    //    exists z in [0 .. |b|-2] . |b| | (z + s) && z <= 0
 | 
			
		||||
                    // <=>
 | 
			
		||||
                    //    |b| | s 
 | 
			
		||||
                    mk_divides(abs_b, s, tmp2);
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    mk_divides(abs_b, sz, tmp2);
 | 
			
		||||
                    mk_and(tmp2, tmp3, tmp4);
 | 
			
		||||
                    mk_divides(abs_b, sz, b_divides_sz);
 | 
			
		||||
                    mk_and(b_divides_sz, asz_bt_le_0, tmp4);
 | 
			
		||||
                    mk_big_or(abs_b - numeral(2), x, tmp4, tmp2);                  
 | 
			
		||||
                   
 | 
			
		||||
                    TRACE("qe",
 | 
			
		||||
                          tout << "b | s + z: " << mk_pp(b_divides_sz, m) << "\n";
 | 
			
		||||
                          tout << "a(s+z) + bt <= 0: " << mk_pp(asz_bt_le_0, m) << "\n";
 | 
			
		||||
                          );                   
 | 
			
		||||
                }
 | 
			
		||||
                mk_flat_and(as_bt_le_0, tmp2, result2); 
 | 
			
		||||
                mk_or(result1, result2, result);
 | 
			
		||||
                simplify(result);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                //    a*s + b*t + (a-1)(b-1) <= 0 
 | 
			
		||||
                // or exists z in [0 .. |b|-2] . |b| | (z + s) && a*n_sign(b)(s + z) + |b|t <= 0
 | 
			
		||||
            }
 | 
			
		||||
            
 | 
			
		||||
            TRACE("qe", 
 | 
			
		||||
                  {
 | 
			
		||||
                      expr_ref_vector trail(m);
 | 
			
		||||
                      tout << "is_strict: " << (is_strict?"true":"false") << "\n";
 | 
			
		||||
                      tout << (is_strict?"strict":"non-strict") << "\n";
 | 
			
		||||
                      bound(m, a, t, false).pp(tout, x);
 | 
			
		||||
                      tout << "\n";
 | 
			
		||||
                      bound(m, b, s, false).pp(tout, x);
 | 
			
		||||
| 
						 | 
				
			
			@ -592,10 +599,6 @@ namespace qe {
 | 
			
		|||
                  });            
 | 
			
		||||
        }
 | 
			
		||||
        
 | 
			
		||||
        void simplify(expr_ref& p) {
 | 
			
		||||
            m_rewriter(p);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        struct mul_lt {
 | 
			
		||||
            arith_util& u;
 | 
			
		||||
            mul_lt(arith_qe_util& u): u(u.m_arith) {}
 | 
			
		||||
| 
						 | 
				
			
			@ -1052,7 +1055,6 @@ namespace qe {
 | 
			
		|||
        }        
 | 
			
		||||
 | 
			
		||||
        bool reduce_equation(expr* p, expr* fml) {
 | 
			
		||||
            TRACE("qe", tout << mk_pp(p, m) << "\n";);
 | 
			
		||||
            numeral k;
 | 
			
		||||
            
 | 
			
		||||
            if (m_arith.is_numeral(p, k) && k.is_zero()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1555,9 +1557,10 @@ public:
 | 
			
		|||
                
 | 
			
		||||
                mk_non_resolve(bounds, true,  is_lower, result);
 | 
			
		||||
                mk_non_resolve(bounds, false, is_lower, result);
 | 
			
		||||
                m_util.simplify(result);
 | 
			
		||||
                add_cache(x, fml, v, result, x_t.get_coeff(), x_t.get_term());
 | 
			
		||||
                TRACE("qe", 
 | 
			
		||||
                        tout << vl << " " << mk_pp(x, m) << "\n";
 | 
			
		||||
                        tout << vl << " " << mk_pp(x, m) << " infinite case\n";
 | 
			
		||||
                        tout << mk_pp(fml, m) << "\n";
 | 
			
		||||
                        tout << mk_pp(result, m) << "\n";);
 | 
			
		||||
                return;
 | 
			
		||||
| 
						 | 
				
			
			@ -1592,18 +1595,21 @@ public:
 | 
			
		|||
            expr_ref t(bounds.exprs(is_strict, is_lower)[index], m);
 | 
			
		||||
            rational a = bounds.coeffs(is_strict, is_lower)[index];
 | 
			
		||||
 | 
			
		||||
            t = x_t.mk_term(a, t);
 | 
			
		||||
            a = x_t.mk_coeff(a);
 | 
			
		||||
            
 | 
			
		||||
                                
 | 
			
		||||
            mk_bounds(bounds, x, true,  is_eq, is_strict, is_lower, index, a, t, result);
 | 
			
		||||
            mk_bounds(bounds, x, false, is_eq, is_strict, is_lower, index, a, t, result);
 | 
			
		||||
 | 
			
		||||
            t = x_t.mk_term(a, t);
 | 
			
		||||
            a = x_t.mk_coeff(a);
 | 
			
		||||
            
 | 
			
		||||
            mk_resolve(bounds, x, x_t, true,  is_eq, is_strict, is_lower, index, a, t, result);
 | 
			
		||||
            mk_resolve(bounds, x, x_t, false, is_eq, is_strict, is_lower, index, a, t, result);
 | 
			
		||||
            m_util.simplify(result);
 | 
			
		||||
            add_cache(x, fml, v, result, x_t.get_coeff(), x_t.get_term());
 | 
			
		||||
            TRACE("qe", 
 | 
			
		||||
                  {
 | 
			
		||||
                      tout << vl << " " << mk_pp(x, m) << "\n";
 | 
			
		||||
                      tout << vl << " " << mk_pp(bounds.atoms(is_strict, is_lower)[index],m) << "\n";
 | 
			
		||||
                      tout << mk_pp(fml, m) << "\n";
 | 
			
		||||
                      tout << mk_pp(result, m) << "\n";
 | 
			
		||||
                  }
 | 
			
		||||
| 
						 | 
				
			
			@ -2225,6 +2231,12 @@ public:
 | 
			
		|||
                }
 | 
			
		||||
            }
 | 
			
		||||
            m_util.simplify(result);
 | 
			
		||||
            TRACE("qe", 
 | 
			
		||||
                  tout << (is_strict?"strict":"non-strict") << "\n";
 | 
			
		||||
                  tout << (is_lower?"is-lower":"is-upper") << "\n";
 | 
			
		||||
                  tout << "a: " << a << " " << mk_pp(t, m) << "\n";
 | 
			
		||||
                  tout << "b: " << b << " " << mk_pp(s, m) << "\n";
 | 
			
		||||
                  tout << mk_pp(result, m) << "\n";);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
| 
						 | 
				
			
			@ -2245,10 +2257,12 @@ public:
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
        void mk_bounds(bounds_proc& bounds, 
 | 
			
		||||
                       app* x,  bool is_strict, bool is_eq_ctx, bool is_strict_ctx, bool is_lower, unsigned index, 
 | 
			
		||||
                       app* x, bool is_strict, bool is_eq_ctx, 
 | 
			
		||||
                       bool is_strict_ctx, bool is_lower, unsigned index, 
 | 
			
		||||
                       rational const& a, expr* t,
 | 
			
		||||
                       expr_ref& result) 
 | 
			
		||||
        {
 | 
			
		||||
            TRACE("qe", tout << mk_pp(t, m) << "\n";);
 | 
			
		||||
            SASSERT(!is_eq_ctx || !is_strict_ctx);
 | 
			
		||||
            unsigned sz = bounds.size(is_strict, is_lower);
 | 
			
		||||
            expr_ref tmp(m), eq(m);            
 | 
			
		||||
| 
						 | 
				
			
			@ -2258,13 +2272,14 @@ public:
 | 
			
		|||
 | 
			
		||||
            for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
                app* e   = bounds.atoms(is_strict, is_lower)[i];
 | 
			
		||||
                expr* s  = bounds.exprs(is_strict, is_lower)[i];
 | 
			
		||||
                expr_ref s(bounds.exprs(is_strict, is_lower)[i], m);
 | 
			
		||||
                rational b = bounds.coeffs(is_strict, is_lower)[i]; 
 | 
			
		||||
               
 | 
			
		||||
                if (same_strict && i == index) {                    
 | 
			
		||||
                    if (non_strict_real) {
 | 
			
		||||
                        m_util.mk_eq(a, x, t, eq);
 | 
			
		||||
                        TRACE("qe", tout << "a:" << a << " x: " << mk_pp(x, m) << " t: " << mk_pp(t, m) << " eq: " << mk_pp(eq, m) << "\n";);
 | 
			
		||||
                        TRACE("qe", tout << "a:" << a << " x: " << mk_pp(x, m) << "t: " << 
 | 
			
		||||
                              mk_pp(t, m) << " eq: " << mk_pp(eq, m) << "\n";);
 | 
			
		||||
                        if (is_eq_ctx) {
 | 
			
		||||
                            m_ctx.add_constraint(true, eq);
 | 
			
		||||
                        }
 | 
			
		||||
| 
						 | 
				
			
			@ -2292,6 +2307,7 @@ public:
 | 
			
		|||
                    (non_strict_real && is_eq_ctx && is_strict) ||
 | 
			
		||||
                    (same_strict && i < index);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
                mk_bound(result_is_strict, is_lower, a, t, b, s, tmp);
 | 
			
		||||
                m_util.m_replace.apply_substitution(e, tmp.get(), result);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -2330,14 +2346,17 @@ public:
 | 
			
		|||
                s = x_t.mk_term(b, s);
 | 
			
		||||
                b = x_t.mk_coeff(b);
 | 
			
		||||
                m_util.mk_resolve(x, strict_resolve, a, t, b, s, tmp);
 | 
			
		||||
                expr_ref save_result(result);
 | 
			
		||||
                m_util.m_replace.apply_substitution(e, tmp.get(), result);
 | 
			
		||||
                
 | 
			
		||||
                m_ctx.add_constraint(true, mk_not(e), tmp);
 | 
			
		||||
 | 
			
		||||
                TRACE("qe_verbose", 
 | 
			
		||||
                      tout << mk_pp(atm, m) << " ";
 | 
			
		||||
                      tout << mk_pp(e, m) << " ==> ";
 | 
			
		||||
                      tout << mk_pp(e, m) << " ==>\n";
 | 
			
		||||
                      tout << mk_pp(tmp, m) << "\n";
 | 
			
		||||
                      tout << "old fml: " << mk_pp(save_result, m) << "\n";
 | 
			
		||||
                      tout << "new fml: " << mk_pp(result, m) << "\n";
 | 
			
		||||
                      );           
 | 
			
		||||
            }            
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ Revision History:
 | 
			
		|||
void theory_arith_params::updt_params(params_ref const & _p) {
 | 
			
		||||
    smt_params_helper p(_p);
 | 
			
		||||
    m_arith_random_initial_value = p.arith_random_initial_value();
 | 
			
		||||
    m_arith_random_seed = p.random_seed();
 | 
			
		||||
    m_arith_mode = static_cast<arith_solver_id>(p.arith_solver());
 | 
			
		||||
    m_nl_arith = p.arith_nl();
 | 
			
		||||
    m_nl_arith_gb = p.arith_nl_gb();
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3945,7 +3945,7 @@ namespace smt {
 | 
			
		|||
              m_fingerprints.display(tout); 
 | 
			
		||||
              );
 | 
			
		||||
        failure fl = get_last_search_failure();
 | 
			
		||||
        if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS) {
 | 
			
		||||
        if (fl == TIMEOUT || fl == MEMOUT || fl == CANCELED || fl == NUM_CONFLICTS || fl == THEORY) {
 | 
			
		||||
            // don't generate model.
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1198,6 +1198,7 @@ namespace smt {
 | 
			
		|||
    void theory_bv::relevant_eh(app * n) {
 | 
			
		||||
        ast_manager & m = get_manager();
 | 
			
		||||
        context & ctx   = get_context();
 | 
			
		||||
        TRACE("bv", tout << "relevant: " << mk_pp(n, m) << "\n";);
 | 
			
		||||
        if (m.is_bool(n)) {
 | 
			
		||||
            bool_var v = ctx.get_bool_var(n);
 | 
			
		||||
            atom * a   = get_bv2a(v);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,18 +51,19 @@ namespace smt {
 | 
			
		|||
 | 
			
		||||
    void theory_fpa::mk_bv_eq(expr * x, expr * y) {
 | 
			
		||||
        SASSERT(get_sort(x)->get_family_id() == m_converter.bu().get_family_id());
 | 
			
		||||
        SASSERT(get_sort(y)->get_family_id() == m_converter.bu().get_family_id());
 | 
			
		||||
        ast_manager & m = get_manager();
 | 
			
		||||
        context & ctx = get_context();  
 | 
			
		||||
        theory_id bv_tid = ctx.get_theory(m.get_sort(x)->get_family_id())->get_id();
 | 
			
		||||
        literal l = mk_eq(x, y, false);
 | 
			
		||||
        ctx.mk_th_axiom(get_id(), 1, &l);
 | 
			
		||||
        ctx.mk_th_axiom(bv_tid, 1, &l);
 | 
			
		||||
        ctx.mark_as_relevant(l);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expr_ref theory_fpa::mk_eq_bv_const(expr_ref const & e) {
 | 
			
		||||
    app_ref theory_fpa::mk_eq_bv_const(expr_ref const & e) {
 | 
			
		||||
        ast_manager & m = get_manager();
 | 
			
		||||
        context & ctx = get_context();
 | 
			
		||||
        expr_ref bv_const(m);
 | 
			
		||||
        app_ref bv_const(m);
 | 
			
		||||
        bv_const = m.mk_fresh_const(0, m.get_sort(e));        
 | 
			
		||||
        mk_bv_eq(bv_const, e);
 | 
			
		||||
        return bv_const;
 | 
			
		||||
| 
						 | 
				
			
			@ -78,6 +79,9 @@ namespace smt {
 | 
			
		|||
        bv_util & bu = m_converter.bu();        
 | 
			
		||||
        expr_ref bv_atom(m);
 | 
			
		||||
 | 
			
		||||
        if (ctx.b_internalized(atom))
 | 
			
		||||
            return true;
 | 
			
		||||
 | 
			
		||||
        unsigned num_args = atom->get_num_args();
 | 
			
		||||
        for (unsigned i = 0; i < num_args; i++)
 | 
			
		||||
            ctx.internalize(atom->get_arg(i), false);
 | 
			
		||||
| 
						 | 
				
			
			@ -135,9 +139,9 @@ namespace smt {
 | 
			
		|||
            simp(a->get_arg(1), sig, pr_sig);
 | 
			
		||||
            simp(a->get_arg(2), exp, pr_exp);
 | 
			
		||||
 | 
			
		||||
            expr_ref bv_v_sgn = mk_eq_bv_const(sgn);
 | 
			
		||||
            expr_ref bv_v_sig = mk_eq_bv_const(sig);
 | 
			
		||||
            expr_ref bv_v_exp = mk_eq_bv_const(exp);
 | 
			
		||||
            app_ref bv_v_sgn = mk_eq_bv_const(sgn);
 | 
			
		||||
            app_ref bv_v_sig = mk_eq_bv_const(sig);
 | 
			
		||||
            app_ref bv_v_exp = mk_eq_bv_const(exp);
 | 
			
		||||
 | 
			
		||||
            m_converter.mk_triple(bv_v_sgn, bv_v_sig, bv_v_exp, bv_term);
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +161,7 @@ namespace smt {
 | 
			
		|||
        SASSERT(!m_trans_map.contains(term));
 | 
			
		||||
        m_trans_map.insert(term, bv_term, 0);
 | 
			
		||||
 | 
			
		||||
        enode * e = ctx.mk_enode(term, false, false, true);        
 | 
			
		||||
        enode * e = (ctx.e_internalized(term)) ? ctx.get_enode(term) : ctx.mk_enode(term, false, false, true);
 | 
			
		||||
        theory_var v = mk_var(e);
 | 
			
		||||
        ctx.attach_th_var(e, this, v);
 | 
			
		||||
        TRACE("t_fpa", tout << "new theory var: " << mk_ismt2_pp(term, get_manager()) << " := " << v << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			@ -437,9 +441,19 @@ namespace smt {
 | 
			
		|||
                ctx.mark_as_relevant(bv_exp);
 | 
			
		||||
            }
 | 
			
		||||
            else if (n->get_decl()->get_decl_kind() == OP_TO_IEEE_BV) {                
 | 
			
		||||
                literal l = mk_eq(n, ex, false);
 | 
			
		||||
                ctx.mark_as_relevant(l);
 | 
			
		||||
                //literal l = mk_eq(n, ex, false);
 | 
			
		||||
                //ctx.mark_as_relevant(l);
 | 
			
		||||
                //ctx.mk_th_axiom(get_id(), 1, &l);
 | 
			
		||||
 | 
			
		||||
                app * ex_a = to_app(ex);
 | 
			
		||||
                if (n->get_id() > ex_a->get_id())
 | 
			
		||||
                    std::swap(n, ex_a);
 | 
			
		||||
                expr_ref eq(m);
 | 
			
		||||
                eq = m.mk_eq(n, ex_a);
 | 
			
		||||
                ctx.internalize(eq, false);
 | 
			
		||||
                literal l = ctx.get_literal(eq);
 | 
			
		||||
                ctx.mk_th_axiom(get_id(), 1, &l);
 | 
			
		||||
                ctx.mark_as_relevant(l);
 | 
			
		||||
            }
 | 
			
		||||
            else
 | 
			
		||||
                NOT_IMPLEMENTED_YET();
 | 
			
		||||
| 
						 | 
				
			
			@ -453,4 +467,7 @@ namespace smt {
 | 
			
		|||
        m_bool_var2atom.reset();  
 | 
			
		||||
        theory::reset_eh();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void theory_fpa::init_model(model_generator & m) {
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -54,6 +54,7 @@ namespace smt {
 | 
			
		|||
        expr_map         m_trans_map;
 | 
			
		||||
        th_trail_stack   m_trail_stack;
 | 
			
		||||
        bool_var2atom    m_bool_var2atom;
 | 
			
		||||
        enode_vector     m_temporaries;
 | 
			
		||||
 | 
			
		||||
        virtual final_check_status final_check_eh() { return FC_DONE; }
 | 
			
		||||
        virtual bool internalize_atom(app * atom, bool gate_ctx);
 | 
			
		||||
| 
						 | 
				
			
			@ -71,6 +72,7 @@ namespace smt {
 | 
			
		|||
        
 | 
			
		||||
        void assign_eh(bool_var v, bool is_true);
 | 
			
		||||
        virtual void relevant_eh(app * n);
 | 
			
		||||
        virtual void init_model(model_generator & m);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        theory_fpa(ast_manager& m);
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +88,7 @@ namespace smt {
 | 
			
		|||
        }
 | 
			
		||||
                
 | 
			
		||||
        void mk_bv_eq(expr * x, expr * y);
 | 
			
		||||
        expr_ref mk_eq_bv_const(expr_ref const & e);
 | 
			
		||||
        app_ref mk_eq_bv_const(expr_ref const & e);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -218,6 +218,7 @@ br_status bv2int_rewriter::mk_mod(expr * s, expr * t, expr_ref & result) {
 | 
			
		|||
    if (is_bv2int(s, s1) && is_bv2int(t, t1)) {
 | 
			
		||||
        align_sizes(s1, t1, false);
 | 
			
		||||
        result = m_bv.mk_bv2int(m_bv.mk_bv_urem(s1, t1));
 | 
			
		||||
        TRACE("bv2int_rewriter", tout << mk_pp(result,m()) << "\n";);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -232,6 +233,7 @@ br_status bv2int_rewriter::mk_mod(expr * s, expr * t, expr_ref & result) {
 | 
			
		|||
        u1 = mk_bv_add(s1, u1, false);
 | 
			
		||||
        align_sizes(u1, t1, false);
 | 
			
		||||
        result = m_bv.mk_bv2int(m_bv.mk_bv_urem(u1, t1));
 | 
			
		||||
        TRACE("bv2int_rewriter", tout << mk_pp(result,m()) << "\n";);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,6 +29,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
    ast_manager &      m;
 | 
			
		||||
    params_ref         m_params;
 | 
			
		||||
    unsigned long long m_max_memory;
 | 
			
		||||
    bool               m_cofactor_equalities;
 | 
			
		||||
    volatile bool      m_cancel;
 | 
			
		||||
 | 
			
		||||
    void checkpoint() { 
 | 
			
		||||
| 
						 | 
				
			
			@ -36,7 +37,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
        if (memory::get_allocation_size() > m_max_memory)
 | 
			
		||||
            throw tactic_exception(TACTIC_MAX_MEMORY_MSG);
 | 
			
		||||
        if (m_cancel)
 | 
			
		||||
            throw tactic_exception(TACTIC_MAX_MEMORY_MSG);
 | 
			
		||||
            throw tactic_exception(TACTIC_CANCELED_MSG);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Collect atoms that contain term if-then-else
 | 
			
		||||
| 
						 | 
				
			
			@ -111,7 +112,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
                frame & fr    = m_frame_stack.back();
 | 
			
		||||
                expr * t      = fr.m_t;
 | 
			
		||||
                bool form_ctx = fr.m_form_ctx;
 | 
			
		||||
                TRACE("cofactor_ite_analyzer", tout << "processing, form_ctx: " << form_ctx << "\n" << mk_bounded_pp(t, m) << "\n";);
 | 
			
		||||
                TRACE("cofactor", tout << "processing, form_ctx: " << form_ctx << "\n" << mk_bounded_pp(t, m) << "\n";);
 | 
			
		||||
 | 
			
		||||
                m_owner.checkpoint();
 | 
			
		||||
                
 | 
			
		||||
| 
						 | 
				
			
			@ -150,7 +151,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
                    }
 | 
			
		||||
                    if (i < num_args) {
 | 
			
		||||
                        m_has_term_ite.mark(t);
 | 
			
		||||
                        TRACE("cofactor_ite_analyzer", tout << "saving candidate: " << form_ctx << "\n" << mk_bounded_pp(t, m) << "\n";);
 | 
			
		||||
                        TRACE("cofactor", tout << "saving candidate: " << form_ctx << "\n" << mk_bounded_pp(t, m) << "\n";);
 | 
			
		||||
                        save_candidate(t, form_ctx);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
| 
						 | 
				
			
			@ -167,6 +168,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    expr * get_first(expr * t) { 
 | 
			
		||||
        TRACE("cofactor", tout << mk_ismt2_pp(t, m) << "\n";);
 | 
			
		||||
        typedef std::pair<expr *, unsigned> frame;
 | 
			
		||||
        expr_fast_mark1         visited;            
 | 
			
		||||
        sbuffer<frame>          stack;    
 | 
			
		||||
| 
						 | 
				
			
			@ -225,6 +227,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
       \brief Fuctor for selecting the term if-then-else condition with the most number of occurrences.
 | 
			
		||||
    */
 | 
			
		||||
    expr * get_best(expr * t) {
 | 
			
		||||
        TRACE("cofactor", tout << mk_ismt2_pp(t, m) << "\n";);
 | 
			
		||||
        typedef std::pair<expr *, unsigned> frame;
 | 
			
		||||
        obj_map<expr, unsigned> occs;
 | 
			
		||||
        expr_fast_mark1         visited;            
 | 
			
		||||
| 
						 | 
				
			
			@ -299,12 +302,17 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
            }
 | 
			
		||||
        }
 | 
			
		||||
        visited.reset();
 | 
			
		||||
        CTRACE("cofactor_ite_get_best", best != 0, tout << "best num-occs: " << best_occs << "\n" << mk_ismt2_pp(best, m) << "\n";);
 | 
			
		||||
        CTRACE("cofactor", best != 0, tout << "best num-occs: " << best_occs << "\n" << mk_ismt2_pp(best, m) << "\n";);
 | 
			
		||||
        return best;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void updt_params(params_ref const & p) {
 | 
			
		||||
        m_max_memory     = megabytes_to_bytes(p.get_uint("max_memory", UINT_MAX));
 | 
			
		||||
        m_cofactor_equalities = p.get_bool("cofactor_equalities", true);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void collect_param_descrs(param_descrs & r) {
 | 
			
		||||
        r.insert("cofactor_equalities", CPK_BOOL, "(default: true) use equalities to rewrite bodies of ite-expressions. This is potentially expensive.");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void set_cancel(bool f) {
 | 
			
		||||
| 
						 | 
				
			
			@ -354,16 +362,16 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
                m_term = 0;
 | 
			
		||||
                expr * lhs;
 | 
			
		||||
                expr * rhs;
 | 
			
		||||
                if (m.is_eq(t, lhs, rhs)) {
 | 
			
		||||
                if (m_owner.m_cofactor_equalities && m.is_eq(t, lhs, rhs)) {
 | 
			
		||||
                    if (m.is_unique_value(lhs)) {
 | 
			
		||||
                        m_term  = rhs;
 | 
			
		||||
                        m_value = to_app(lhs); 
 | 
			
		||||
                        TRACE("set_cofactor_atom", tout << "term:\n" << mk_ismt2_pp(m_term, m) << "\nvalue: " << mk_ismt2_pp(m_value, m) << "\n";);
 | 
			
		||||
                        TRACE("cofactor", tout << "term:\n" << mk_ismt2_pp(m_term, m) << "\nvalue: " << mk_ismt2_pp(m_value, m) << "\n";);
 | 
			
		||||
                    }
 | 
			
		||||
                    else if (m.is_unique_value(rhs)) {
 | 
			
		||||
                        m_term  = lhs;
 | 
			
		||||
                        m_value = to_app(rhs);
 | 
			
		||||
                        TRACE("set_cofactor_atom", tout << "term:\n" << mk_ismt2_pp(m_term, m) << "\nvalue: " << mk_ismt2_pp(m_value, m) << "\n";);
 | 
			
		||||
                        TRACE("cofactor", tout << "term:\n" << mk_ismt2_pp(m_term, m) << "\nvalue: " << mk_ismt2_pp(m_value, m) << "\n";);
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                // TODO: bounds
 | 
			
		||||
| 
						 | 
				
			
			@ -467,7 +475,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
                    m_cofactor.set_cofactor_atom(neg_c);
 | 
			
		||||
                    m_cofactor(curr, neg_cofactor);
 | 
			
		||||
                    curr = m.mk_ite(c, pos_cofactor, neg_cofactor);
 | 
			
		||||
                    TRACE("cofactor_ite", tout << "cofactor_ite step: " << step << "\n" << mk_ismt2_pp(curr, m) << "\n";);
 | 
			
		||||
                    TRACE("cofactor", tout << "cofactor_ite step: " << step << "\n" << mk_ismt2_pp(curr, m) << "\n";);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            return false;
 | 
			
		||||
| 
						 | 
				
			
			@ -522,7 +530,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
        
 | 
			
		||||
        void cofactor(expr * t, expr_ref & r) {
 | 
			
		||||
            unsigned step = 0;
 | 
			
		||||
            TRACE("cofactor_ite", tout << "cofactor target:\n" << mk_ismt2_pp(t, m) << "\n";);
 | 
			
		||||
            TRACE("cofactor", tout << "cofactor target:\n" << mk_ismt2_pp(t, m) << "\n";);
 | 
			
		||||
            expr_ref curr(m);
 | 
			
		||||
            curr = t;
 | 
			
		||||
            while (true) {
 | 
			
		||||
| 
						 | 
				
			
			@ -543,21 +551,20 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
                m_cofactor(curr, neg_cofactor);
 | 
			
		||||
                if (pos_cofactor == neg_cofactor) {
 | 
			
		||||
                    curr = pos_cofactor;
 | 
			
		||||
                    TRACE("cofactor_ite", tout << "cofactor_ite step: " << step << "\n" << mk_ismt2_pp(curr, m) << "\n";);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                if (m.is_true(pos_cofactor) && m.is_false(neg_cofactor)) {
 | 
			
		||||
                else if (m.is_true(pos_cofactor) && m.is_false(neg_cofactor)) {
 | 
			
		||||
                    curr = c;
 | 
			
		||||
                    TRACE("cofactor_ite", tout << "cofactor_ite step: " << step << "\n" << mk_ismt2_pp(curr, m) << "\n";);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                if (m.is_false(pos_cofactor) && m.is_true(neg_cofactor)) {
 | 
			
		||||
                else if (m.is_false(pos_cofactor) && m.is_true(neg_cofactor)) {
 | 
			
		||||
                    curr = neg_c;
 | 
			
		||||
                    TRACE("cofactor_ite", tout << "cofactor_ite step: " << step << "\n" << mk_ismt2_pp(curr, m) << "\n";);
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    curr = m.mk_ite(c, pos_cofactor, neg_cofactor);
 | 
			
		||||
                TRACE("cofactor_ite", tout << "cofactor_ite step: " << step << "\n" << mk_ismt2_pp(curr, m) << "\n";);
 | 
			
		||||
                }
 | 
			
		||||
                TRACE("cofactor", 
 | 
			
		||||
                      tout << "cofactor_ite step: " << step << "\n";
 | 
			
		||||
                      tout << "cofactor: " << mk_ismt2_pp(c, m) << "\n";
 | 
			
		||||
                      tout << mk_ismt2_pp(curr, m) << "\n";);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -570,6 +577,7 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
        
 | 
			
		||||
        void operator()(expr * t, expr_ref & r) {
 | 
			
		||||
            ptr_vector<expr> new_args;
 | 
			
		||||
            SASSERT(m_frames.empty());
 | 
			
		||||
            m_frames.push_back(frame(t, true));
 | 
			
		||||
            while (!m_frames.empty()) {
 | 
			
		||||
                m_owner.checkpoint();
 | 
			
		||||
| 
						 | 
				
			
			@ -649,7 +657,8 @@ struct cofactor_elim_term_ite::imp {
 | 
			
		|||
 | 
			
		||||
    imp(ast_manager & _m, params_ref const & p):
 | 
			
		||||
        m(_m),
 | 
			
		||||
        m_params(p) {
 | 
			
		||||
        m_params(p),
 | 
			
		||||
        m_cofactor_equalities(true) {
 | 
			
		||||
        m_cancel = false;
 | 
			
		||||
        updt_params(p);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -686,7 +695,8 @@ void cofactor_elim_term_ite::updt_params(params_ref const & p) {
 | 
			
		|||
    m_imp->updt_params(p);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cofactor_elim_term_ite::get_param_descrs(param_descrs & r) {
 | 
			
		||||
void cofactor_elim_term_ite::collect_param_descrs(param_descrs & r) {
 | 
			
		||||
    m_imp->collect_param_descrs(r);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void cofactor_elim_term_ite::operator()(expr * t, expr_ref & r) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,7 +31,7 @@ public:
 | 
			
		|||
    virtual ~cofactor_elim_term_ite();
 | 
			
		||||
 | 
			
		||||
    void updt_params(params_ref const & p);
 | 
			
		||||
    static void get_param_descrs(param_descrs & r);
 | 
			
		||||
    void collect_param_descrs(param_descrs & r);
 | 
			
		||||
 | 
			
		||||
    void operator()(expr * t, expr_ref & r);
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -52,8 +52,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    virtual ~cofactor_term_ite_tactic() {}
 | 
			
		||||
    virtual void updt_params(params_ref const & p) { m_params = p; m_elim_ite.updt_params(p); }
 | 
			
		||||
    static  void get_param_descrs(param_descrs & r) { cofactor_elim_term_ite::get_param_descrs(r); }
 | 
			
		||||
    virtual void collect_param_descrs(param_descrs & r) { get_param_descrs(r); }
 | 
			
		||||
    virtual void collect_param_descrs(param_descrs & r) { m_elim_ite.collect_param_descrs(r); }
 | 
			
		||||
    
 | 
			
		||||
    virtual void operator()(goal_ref const & g, 
 | 
			
		||||
                            goal_ref_buffer & result, 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -43,6 +43,7 @@ void filter_model_converter::operator()(model_ref & old_model, unsigned goal_idx
 | 
			
		|||
        if (fs.is_marked(f))
 | 
			
		||||
            continue;
 | 
			
		||||
        func_interp * fi = old_model->get_func_interp(f);
 | 
			
		||||
        SASSERT(fi);
 | 
			
		||||
        new_model->register_decl(f, fi->copy());
 | 
			
		||||
    }
 | 
			
		||||
    new_model->copy_usort_interps(*old_model);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -166,6 +166,14 @@ public:
 | 
			
		|||
        return e->get_data().m_value;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    value const & operator[](key * k) const {
 | 
			
		||||
        return find(k);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    value & operator[](key * k) {
 | 
			
		||||
        return find(k);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    iterator find_iterator(Key * k) const { 
 | 
			
		||||
        return m_table.find(key_data(k));
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue