mirror of
				https://github.com/Z3Prover/z3
				synced 2025-11-04 05:19:11 +00:00 
			
		
		
		
	merged with unstable
This commit is contained in:
		
						commit
						3a0947b3ba
					
				
					 413 changed files with 31618 additions and 17204 deletions
				
			
		
							
								
								
									
										1
									
								
								.gitattributes
									
										
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.gitattributes
									
										
									
									
										vendored
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1 @@
 | 
			
		|||
src/api/dotnet/Properties/AssemblyInfo.cs text eol=crlf
 | 
			
		||||
| 
						 | 
				
			
			@ -63,6 +63,8 @@ Version 4.3.2
 | 
			
		|||
 | 
			
		||||
- Fixed bug reported at http://z3.codeplex.com/workitem/23 (Thanks to Paul Jackson).
 | 
			
		||||
 | 
			
		||||
- Fixed bug reported at http://stackoverflow.com/questions/15226944/segmentation-fault-in-z3 (Thanks to Tianhai Liu).
 | 
			
		||||
 | 
			
		||||
Version 4.3.1
 | 
			
		||||
=============
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -906,6 +906,72 @@ void enum_sort_example() {
 | 
			
		|||
    std::cout << "2: " << result_goal.as_expr() << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void expr_vector_example() {
 | 
			
		||||
    std::cout << "expr_vector example\n";
 | 
			
		||||
    context c;
 | 
			
		||||
    const unsigned N = 10;
 | 
			
		||||
 | 
			
		||||
    expr_vector x(c);
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) { 
 | 
			
		||||
        std::stringstream x_name; 
 | 
			
		||||
        x_name << "x_" << i;
 | 
			
		||||
        x.push_back(c.int_const(x_name.str().c_str()));
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    solver s(c);
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) {
 | 
			
		||||
        s.add(x[i] >= 1);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::cout << s << "\n" << "solving...\n" << s.check() << "\n";
 | 
			
		||||
    model m = s.get_model();
 | 
			
		||||
    std::cout << "solution\n" << m;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void exists_expr_vector_example() {
 | 
			
		||||
    std::cout << "exists expr_vector example\n";
 | 
			
		||||
    context c;
 | 
			
		||||
    const unsigned N = 10;
 | 
			
		||||
 | 
			
		||||
    expr_vector xs(c);
 | 
			
		||||
    expr x(c);
 | 
			
		||||
    expr b(c);
 | 
			
		||||
    b = c.bool_val(true); 
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < N; i++) { 
 | 
			
		||||
        std::stringstream x_name; 
 | 
			
		||||
        x_name << "x_" << i;
 | 
			
		||||
        x = c.int_const(x_name.str().c_str());
 | 
			
		||||
        xs.push_back(x);
 | 
			
		||||
        b = b && x >= 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expr ex(c);
 | 
			
		||||
    ex = exists(xs, b);
 | 
			
		||||
    std::cout << ex << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void substitute_example() {
 | 
			
		||||
    std::cout << "substitute example\n";
 | 
			
		||||
    context c;
 | 
			
		||||
    expr x(c);
 | 
			
		||||
    x = c.int_const("x");
 | 
			
		||||
    expr f(c);
 | 
			
		||||
    f = (x == 2) || (x == 1);
 | 
			
		||||
    std::cout << f << std::endl;
 | 
			
		||||
 | 
			
		||||
    expr two(c), three(c);
 | 
			
		||||
    two   = c.int_val(2);
 | 
			
		||||
    three = c.int_val(3);
 | 
			
		||||
    Z3_ast from[] = { two };
 | 
			
		||||
    Z3_ast to[]   = { three };
 | 
			
		||||
    expr new_f(c);
 | 
			
		||||
    new_f = to_expr(c, Z3_substitute(c, f, 1, from, to));
 | 
			
		||||
    
 | 
			
		||||
    std::cout << new_f << std::endl;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int main() {
 | 
			
		||||
    try {
 | 
			
		||||
        demorgan(); std::cout << "\n";
 | 
			
		||||
| 
						 | 
				
			
			@ -937,10 +1003,13 @@ int main() {
 | 
			
		|||
        tactic_example9(); std::cout << "\n";
 | 
			
		||||
        tactic_qe(); std::cout << "\n";
 | 
			
		||||
        tst_visit(); std::cout << "\n";
 | 
			
		||||
	incremental_example1(); std::cout << "\n";
 | 
			
		||||
	incremental_example2(); std::cout << "\n";
 | 
			
		||||
	incremental_example3(); std::cout << "\n";
 | 
			
		||||
        incremental_example1(); std::cout << "\n";
 | 
			
		||||
        incremental_example2(); std::cout << "\n";
 | 
			
		||||
        incremental_example3(); std::cout << "\n";
 | 
			
		||||
        enum_sort_example(); std::cout << "\n";
 | 
			
		||||
        expr_vector_example(); std::cout << "\n";
 | 
			
		||||
        exists_expr_vector_example(); std::cout << "\n";
 | 
			
		||||
        substitute_example(); std::cout << "\n";
 | 
			
		||||
        std::cout << "done\n";
 | 
			
		||||
    }
 | 
			
		||||
    catch (exception & ex) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -474,7 +474,7 @@ namespace test_mapi
 | 
			
		|||
                cells_c[i] = new BoolExpr[9];
 | 
			
		||||
                for (uint j = 0; j < 9; j++)
 | 
			
		||||
                    cells_c[i][j] = ctx.MkAnd(ctx.MkLe(ctx.MkInt(1), X[i][j]),
 | 
			
		||||
                                                ctx.MkLe(X[i][j], ctx.MkInt(9)));
 | 
			
		||||
                                              ctx.MkLe(X[i][j], ctx.MkInt(9)));
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // each row contains a digit at most once
 | 
			
		||||
| 
						 | 
				
			
			@ -485,7 +485,13 @@ namespace test_mapi
 | 
			
		|||
            // each column contains a digit at most once
 | 
			
		||||
            BoolExpr[] cols_c = new BoolExpr[9];
 | 
			
		||||
            for (uint j = 0; j < 9; j++)
 | 
			
		||||
                cols_c[j] = ctx.MkDistinct(X[j]);
 | 
			
		||||
            {
 | 
			
		||||
                IntExpr[] column = new IntExpr[9];
 | 
			
		||||
                for (uint i = 0; i < 9; i++)
 | 
			
		||||
                    column[i] = X[i][j];
 | 
			
		||||
 | 
			
		||||
                cols_c[j] = ctx.MkDistinct(column);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            // each 3x3 square contains a digit at most once
 | 
			
		||||
            BoolExpr[][] sq_c = new BoolExpr[3][];
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										18
									
								
								examples/tptp/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								examples/tptp/README
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,18 @@
 | 
			
		|||
TPTP front-end and utilities as a sample using the C++ bindings.
 | 
			
		||||
To build the example execute
 | 
			
		||||
   make examples
 | 
			
		||||
in the build directory.
 | 
			
		||||
 | 
			
		||||
This command will create the executable tptp.
 | 
			
		||||
On Windows, you can just execute it.
 | 
			
		||||
On OSX and Linux, you must install z3 first using 
 | 
			
		||||
   sudo make install
 | 
			
		||||
OR update LD_LIBRARY_PATH (Linux) or DYLD_LIBRARY_PATH (OSX) 
 | 
			
		||||
   with the build directory. You need that to be able to 
 | 
			
		||||
   find the Z3 shared library.
 | 
			
		||||
 | 
			
		||||
The sample illustrates using Z3 from the TPTP language.
 | 
			
		||||
The TPTP language is documented on http://tptp.org
 | 
			
		||||
It also exposes utilities for converting between SMT-LIB 
 | 
			
		||||
and TPTP format.
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										2480
									
								
								examples/tptp/tptp5.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2480
									
								
								examples/tptp/tptp5.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										38
									
								
								examples/tptp/tptp5.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								examples/tptp/tptp5.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,38 @@
 | 
			
		|||
#ifndef TPTP5_H_
 | 
			
		||||
#define TPTP5_H_
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
class TreeNode;
 | 
			
		||||
 | 
			
		||||
#if 0
 | 
			
		||||
class named_formulas {
 | 
			
		||||
    expr_ref_vector m_fmls;
 | 
			
		||||
    svector<symbol> m_names;
 | 
			
		||||
    bool m_has_conjecture;
 | 
			
		||||
    unsigned m_conjecture_index;
 | 
			
		||||
public:
 | 
			
		||||
    named_formulas(ast_manager& m) : 
 | 
			
		||||
        m_fmls(m), 
 | 
			
		||||
        m_has_conjecture(false),
 | 
			
		||||
        m_conjecture_index(0)
 | 
			
		||||
        {}
 | 
			
		||||
    void push_back(expr* fml, char const* name) {
 | 
			
		||||
        m_fmls.push_back(fml);
 | 
			
		||||
        m_names.push_back(symbol(name));
 | 
			
		||||
    }
 | 
			
		||||
    unsigned size() const { return m_fmls.size(); }
 | 
			
		||||
    expr*const* c_ptr() const { return m_fmls.c_ptr(); }
 | 
			
		||||
    expr* operator[](unsigned i) { return m_fmls[i].get(); }
 | 
			
		||||
    symbol const& name(unsigned i) { return m_names[i]; }
 | 
			
		||||
    void set_has_conjecture() { 
 | 
			
		||||
        m_has_conjecture = true;
 | 
			
		||||
        m_conjecture_index = m_fmls.size();
 | 
			
		||||
    }
 | 
			
		||||
    bool has_conjecture() const { return m_has_conjecture; }
 | 
			
		||||
    unsigned conjecture_index() const { return m_conjecture_index; }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
bool tptp5_parse(ast_manager& m, char const* filename, named_formulas& fmls);
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
							
								
								
									
										2672
									
								
								examples/tptp/tptp5.lex.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										2672
									
								
								examples/tptp/tptp5.lex.cpp
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										4475
									
								
								examples/tptp/tptp5.tab.c
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										4475
									
								
								examples/tptp/tptp5.tab.c
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							
							
								
								
									
										138
									
								
								examples/tptp/tptp5.tab.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										138
									
								
								examples/tptp/tptp5.tab.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,138 @@
 | 
			
		|||
/* A Bison parser, made by GNU Bison 2.4.2.  */
 | 
			
		||||
 | 
			
		||||
/* Skeleton interface for Bison's Yacc-like parsers in C
 | 
			
		||||
   
 | 
			
		||||
      Copyright (C) 1984, 1989-1990, 2000-2006, 2009-2010 Free Software
 | 
			
		||||
   Foundation, Inc.
 | 
			
		||||
   
 | 
			
		||||
   This program is free software: you can redistribute it and/or modify
 | 
			
		||||
   it under the terms of the GNU General Public License as published by
 | 
			
		||||
   the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
   (at your option) any later version.
 | 
			
		||||
   
 | 
			
		||||
   This program is distributed in the hope that it will be useful,
 | 
			
		||||
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
   GNU General Public License for more details.
 | 
			
		||||
   
 | 
			
		||||
   You should have received a copy of the GNU General Public License
 | 
			
		||||
   along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 | 
			
		||||
 | 
			
		||||
/* As a special exception, you may create a larger work that contains
 | 
			
		||||
   part or all of the Bison parser skeleton and distribute that work
 | 
			
		||||
   under terms of your choice, so long as that work isn't itself a
 | 
			
		||||
   parser generator using the skeleton or a modified version thereof
 | 
			
		||||
   as a parser skeleton.  Alternatively, if you modify or redistribute
 | 
			
		||||
   the parser skeleton itself, you may (at your option) remove this
 | 
			
		||||
   special exception, which will cause the skeleton and the resulting
 | 
			
		||||
   Bison output files to be licensed under the GNU General Public
 | 
			
		||||
   License without this special exception.
 | 
			
		||||
   
 | 
			
		||||
   This special exception was added by the Free Software Foundation in
 | 
			
		||||
   version 2.2 of Bison.  */
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Tokens.  */
 | 
			
		||||
#ifndef YYTOKENTYPE
 | 
			
		||||
# define YYTOKENTYPE
 | 
			
		||||
   /* Put the tokens into the symbol table, so that GDB and other debuggers
 | 
			
		||||
      know about them.  */
 | 
			
		||||
   enum yytokentype {
 | 
			
		||||
     AMPERSAND = 258,
 | 
			
		||||
     AT_SIGN = 259,
 | 
			
		||||
     AT_SIGN_MINUS = 260,
 | 
			
		||||
     AT_SIGN_PLUS = 261,
 | 
			
		||||
     CARET = 262,
 | 
			
		||||
     COLON = 263,
 | 
			
		||||
     COLON_EQUALS = 264,
 | 
			
		||||
     COMMA = 265,
 | 
			
		||||
     EQUALS = 266,
 | 
			
		||||
     EQUALS_GREATER = 267,
 | 
			
		||||
     EXCLAMATION = 268,
 | 
			
		||||
     EXCLAMATION_EQUALS = 269,
 | 
			
		||||
     EXCLAMATION_EXCLAMATION = 270,
 | 
			
		||||
     EXCLAMATION_GREATER = 271,
 | 
			
		||||
     LBRKT = 272,
 | 
			
		||||
     LESS_EQUALS = 273,
 | 
			
		||||
     LESS_EQUALS_GREATER = 274,
 | 
			
		||||
     LESS_TILDE_GREATER = 275,
 | 
			
		||||
     LPAREN = 276,
 | 
			
		||||
     MINUS = 277,
 | 
			
		||||
     MINUS_MINUS_GREATER = 278,
 | 
			
		||||
     PERIOD = 279,
 | 
			
		||||
     QUESTION = 280,
 | 
			
		||||
     QUESTION_QUESTION = 281,
 | 
			
		||||
     QUESTION_STAR = 282,
 | 
			
		||||
     RBRKT = 283,
 | 
			
		||||
     RPAREN = 284,
 | 
			
		||||
     STAR = 285,
 | 
			
		||||
     TILDE = 286,
 | 
			
		||||
     TILDE_AMPERSAND = 287,
 | 
			
		||||
     TILDE_VLINE = 288,
 | 
			
		||||
     VLINE = 289,
 | 
			
		||||
     _DLR_cnf = 290,
 | 
			
		||||
     _DLR_fof = 291,
 | 
			
		||||
     _DLR_fot = 292,
 | 
			
		||||
     _DLR_itef = 293,
 | 
			
		||||
     _DLR_itetf = 294,
 | 
			
		||||
     _DLR_itett = 295,
 | 
			
		||||
     _DLR_tff = 296,
 | 
			
		||||
     _DLR_thf = 297,
 | 
			
		||||
     _LIT_cnf = 298,
 | 
			
		||||
     _LIT_fof = 299,
 | 
			
		||||
     _LIT_include = 300,
 | 
			
		||||
     _LIT_tff = 301,
 | 
			
		||||
     _LIT_thf = 302,
 | 
			
		||||
     arrow = 303,
 | 
			
		||||
     comment = 304,
 | 
			
		||||
     comment_line = 305,
 | 
			
		||||
     decimal = 306,
 | 
			
		||||
     decimal_exponent = 307,
 | 
			
		||||
     decimal_fraction = 308,
 | 
			
		||||
     distinct_object = 309,
 | 
			
		||||
     dollar_dollar_word = 310,
 | 
			
		||||
     dollar_word = 311,
 | 
			
		||||
     dot_decimal = 312,
 | 
			
		||||
     integer = 313,
 | 
			
		||||
     less_sign = 314,
 | 
			
		||||
     lower_word = 315,
 | 
			
		||||
     plus = 316,
 | 
			
		||||
     positive_decimal = 317,
 | 
			
		||||
     rational = 318,
 | 
			
		||||
     real = 319,
 | 
			
		||||
     signed_integer = 320,
 | 
			
		||||
     signed_rational = 321,
 | 
			
		||||
     signed_real = 322,
 | 
			
		||||
     single_quoted = 323,
 | 
			
		||||
     star = 324,
 | 
			
		||||
     unrecognized = 325,
 | 
			
		||||
     unsigned_integer = 326,
 | 
			
		||||
     unsigned_rational = 327,
 | 
			
		||||
     unsigned_real = 328,
 | 
			
		||||
     upper_word = 329,
 | 
			
		||||
     vline = 330
 | 
			
		||||
   };
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
 | 
			
		||||
typedef union YYSTYPE
 | 
			
		||||
{
 | 
			
		||||
 | 
			
		||||
/* Line 1685 of yacc.c  */
 | 
			
		||||
#line 148 "tptp5.y"
 | 
			
		||||
int ival; double dval; char* sval; TreeNode* pval;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
/* Line 1685 of yacc.c  */
 | 
			
		||||
#line 130 "tptp5.tab.h"
 | 
			
		||||
} YYSTYPE;
 | 
			
		||||
# define YYSTYPE_IS_TRIVIAL 1
 | 
			
		||||
# define yystype YYSTYPE /* obsolescent; will be withdrawn */
 | 
			
		||||
# define YYSTYPE_IS_DECLARED 1
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern YYSTYPE yylval;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -14,6 +14,7 @@ def init_project_def():
 | 
			
		|||
    add_lib('polynomial', ['util'], 'math/polynomial')
 | 
			
		||||
    add_lib('sat', ['util'])
 | 
			
		||||
    add_lib('nlsat', ['polynomial', 'sat'])
 | 
			
		||||
    add_lib('hilbert', ['util'], 'math/hilbert')
 | 
			
		||||
    add_lib('interval', ['util'], 'math/interval')
 | 
			
		||||
    add_lib('realclosure', ['interval'], 'math/realclosure')
 | 
			
		||||
    add_lib('subpaving', ['interval'], 'math/subpaving')
 | 
			
		||||
| 
						 | 
				
			
			@ -55,11 +56,19 @@ def init_project_def():
 | 
			
		|||
    add_lib('smt_tactic', ['smt'], 'smt/tactic')
 | 
			
		||||
    add_lib('sls_tactic', ['tactic', 'normal_forms', 'core_tactics', 'bv_tactics'], 'tactic/sls')
 | 
			
		||||
    add_lib('duality', ['smt', 'interp'])
 | 
			
		||||
    # TODO: split muz_qe inbto muz, qe. Perhaps, we should also consider breaking muz into muz and pdr.
 | 
			
		||||
    add_lib('muz_qe', ['smt', 'sat', 'smt2parser', 'duality'])
 | 
			
		||||
    add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'muz_qe'], 'tactic/smtlogics')
 | 
			
		||||
    add_lib('qe', ['smt','sat'], 'qe')
 | 
			
		||||
    add_lib('muz', ['smt', 'sat', 'smt2parser', 'aig_tactic', 'qe'], 'muz/base')
 | 
			
		||||
    add_lib('transforms', ['muz', 'hilbert'], 'muz/transforms')
 | 
			
		||||
    add_lib('rel', ['muz', 'transforms'], 'muz/rel')
 | 
			
		||||
    add_lib('pdr', ['muz', 'transforms', 'arith_tactics', 'smt_tactic'], 'muz/pdr')
 | 
			
		||||
    add_lib('clp', ['muz', 'transforms'], 'muz/clp')
 | 
			
		||||
    add_lib('tab', ['muz', 'transforms'], 'muz/tab')
 | 
			
		||||
    add_lib('bmc', ['muz', 'transforms'], 'muz/bmc')
 | 
			
		||||
    add_lib('duality_intf', ['muz', 'transforms', 'duality'], 'muz/duality')
 | 
			
		||||
    add_lib('fp',  ['muz', 'pdr', 'clp', 'tab', 'rel', 'bmc', 'duality_intf'], 'muz/fp')
 | 
			
		||||
    add_lib('smtlogic_tactics', ['arith_tactics', 'bv_tactics', 'nlsat_tactic', 'smt_tactic', 'aig_tactic', 'fp', 'muz','qe'], 'tactic/smtlogics')
 | 
			
		||||
    add_lib('ufbv_tactic', ['normal_forms', 'core_tactics', 'macros', 'smt_tactic', 'rewriter'], 'tactic/ufbv')
 | 
			
		||||
    add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'muz_qe', 'sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
 | 
			
		||||
    add_lib('portfolio', ['smtlogic_tactics', 'ufbv_tactic', 'fpa', 'aig_tactic', 'fp',  'qe','sls_tactic', 'subpaving_tactic'], 'tactic/portfolio')
 | 
			
		||||
    add_lib('smtparser', ['portfolio'], 'parsers/smt')
 | 
			
		||||
#    add_dll('foci2', ['util'], 'interp/foci2stub', 
 | 
			
		||||
#            dll_name='foci2', 
 | 
			
		||||
| 
						 | 
				
			
			@ -82,6 +91,7 @@ def init_project_def():
 | 
			
		|||
    # Examples
 | 
			
		||||
    add_cpp_example('cpp_example', 'c++') 
 | 
			
		||||
    add_cpp_example('iz3', 'interp') 
 | 
			
		||||
    add_cpp_example('z3_tptp', 'tptp') 
 | 
			
		||||
    add_c_example('c_example', 'c')
 | 
			
		||||
    add_c_example('maxsat')
 | 
			
		||||
    add_dotnet_example('dotnet_example', 'dotnet')
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -292,7 +292,7 @@ def check_java():
 | 
			
		|||
        print("Finding jni.h...")
 | 
			
		||||
 | 
			
		||||
    if JNI_HOME != None:
 | 
			
		||||
        if not os.path.exists(path.join(JNI_HOME, 'jni.h')):
 | 
			
		||||
        if not os.path.exists(os.path.join(JNI_HOME, 'jni.h')):
 | 
			
		||||
            raise MKException("Failed to detect jni.h '%s'; the environment variable JNI_HOME is probably set to the wrong path." % os.path.join(JNI_HOME))
 | 
			
		||||
    else:        
 | 
			
		||||
        # Search for jni.h in the library directories...
 | 
			
		||||
| 
						 | 
				
			
			@ -952,6 +952,9 @@ class ExtraExeComponent(ExeComponent):
 | 
			
		|||
    def main_component(self):
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
    def require_mem_initializer(self):
 | 
			
		||||
        return False
 | 
			
		||||
 | 
			
		||||
def get_so_ext():
 | 
			
		||||
    sysname = os.uname()[0]
 | 
			
		||||
    if sysname == 'Darwin':
 | 
			
		||||
| 
						 | 
				
			
			@ -1117,20 +1120,19 @@ class DotNetDLLComponent(Component):
 | 
			
		|||
                    cs_fp_files.append(os.path.join(self.to_src_dir, self.assembly_info_dir, cs_file))
 | 
			
		||||
                    cs_files.append(os.path.join(self.assembly_info_dir, cs_file))
 | 
			
		||||
            dllfile = '%s.dll' % self.dll_name
 | 
			
		||||
            out.write('%s:' % dllfile)
 | 
			
		||||
            out.write('%s: %s$(SO_EXT)' % (dllfile, get_component(Z3_DLL_COMPONENT).dll_name))
 | 
			
		||||
            for cs_file in cs_fp_files:
 | 
			
		||||
                out.write(' ')
 | 
			
		||||
                out.write(cs_file)
 | 
			
		||||
            out.write('\n')
 | 
			
		||||
            out.write('  cd %s && csc /noconfig /unsafe+ /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:mscorlib.dll /reference:System.Core.dll /reference:System.dll /reference:System.Numerics.dll /debug+ /debug:full /filealign:512 /optimize- /out:%s.dll /target:library' % (self.to_src_dir, self.dll_name))
 | 
			
		||||
            out.write('  csc /noconfig /unsafe+ /nowarn:1701,1702 /nostdlib+ /errorreport:prompt /warn:4 /define:DEBUG;TRACE /reference:mscorlib.dll /reference:System.Core.dll /reference:System.dll /reference:System.Numerics.dll /debug+ /debug:full /filealign:512 /optimize- /linkresource:%s.dll /out:%s.dll /target:library' % (get_component(Z3_DLL_COMPONENT).dll_name, self.dll_name))
 | 
			
		||||
            if VS_X64:
 | 
			
		||||
                out.write(' /platform:x64')
 | 
			
		||||
            else:
 | 
			
		||||
                out.write(' /platform:x86')
 | 
			
		||||
            for cs_file in cs_files:
 | 
			
		||||
                out.write(' ')
 | 
			
		||||
                out.write(cs_file)
 | 
			
		||||
                out.write(' %s' % os.path.join(self.to_src_dir, cs_file))
 | 
			
		||||
            out.write('\n')
 | 
			
		||||
            # HACK
 | 
			
		||||
            win_to_src_dir = self.to_src_dir.replace('/', '\\')
 | 
			
		||||
            out.write('  move %s\n' % os.path.join(win_to_src_dir, dllfile))
 | 
			
		||||
            out.write('  move %s.pdb\n' % os.path.join(win_to_src_dir, self.dll_name))
 | 
			
		||||
            out.write('%s: %s\n\n' % (self.name, dllfile))
 | 
			
		||||
            return
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -1256,7 +1258,7 @@ class CppExampleComponent(ExampleComponent):
 | 
			
		|||
            out.write(' ')
 | 
			
		||||
            out.write(os.path.join(self.to_ex_dir, cppfile))
 | 
			
		||||
        out.write('\n')
 | 
			
		||||
        out.write('\t%s $(EXAMP_DEBUG_FLAG) $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % (self.compiler(), exefile))
 | 
			
		||||
        out.write('\t%s $(OS_DEFINES) $(EXAMP_DEBUG_FLAG) $(LINK_OUT_FLAG)%s $(LINK_FLAGS)' % (self.compiler(), exefile))
 | 
			
		||||
        # Add include dir components
 | 
			
		||||
        out.write(' -I%s' % get_component(API_COMPONENT).to_src_dir)
 | 
			
		||||
        out.write(' -I%s' % get_component(CPP_COMPONENT).to_src_dir)
 | 
			
		||||
| 
						 | 
				
			
			@ -1428,7 +1430,8 @@ def mk_config():
 | 
			
		|||
            'LINK_OUT_FLAG=/Fe\n'
 | 
			
		||||
            'SO_EXT=.dll\n'
 | 
			
		||||
            'SLINK=cl\n'
 | 
			
		||||
            'SLINK_OUT_FLAG=/Fe\n')
 | 
			
		||||
            'SLINK_OUT_FLAG=/Fe\n'
 | 
			
		||||
	    'OS_DEFINES=/D _WINDOWS\n')
 | 
			
		||||
        extra_opt = ''
 | 
			
		||||
        if GIT_HASH:
 | 
			
		||||
            extra_opt = '%s /D Z3GITHASH=%s' % (extra_opt, GIT_HASH)
 | 
			
		||||
| 
						 | 
				
			
			@ -1476,6 +1479,7 @@ def mk_config():
 | 
			
		|||
                print('Java Compiler:  %s' % JAVAC)
 | 
			
		||||
    else:
 | 
			
		||||
        global CXX, CC, GMP, FOCI2, CPPFLAGS, CXXFLAGS, LDFLAGS, EXAMP_DEBUG_FLAG
 | 
			
		||||
	OS_DEFINES = ""
 | 
			
		||||
        ARITH = "internal"
 | 
			
		||||
        check_ar()
 | 
			
		||||
        CXX = find_cxx_compiler()
 | 
			
		||||
| 
						 | 
				
			
			@ -1526,18 +1530,21 @@ def mk_config():
 | 
			
		|||
            SLIBFLAGS = '-dynamiclib'
 | 
			
		||||
        elif sysname == 'Linux':
 | 
			
		||||
            CXXFLAGS       = '%s -fno-strict-aliasing -D_LINUX_' % CXXFLAGS
 | 
			
		||||
	    OS_DEFINES     = '-D_LINUX'
 | 
			
		||||
            SO_EXT         = '.so'
 | 
			
		||||
            LDFLAGS        = '%s -lrt' % LDFLAGS
 | 
			
		||||
            SLIBFLAGS      = '-shared'
 | 
			
		||||
            SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
 | 
			
		||||
        elif sysname == 'FreeBSD':
 | 
			
		||||
            CXXFLAGS       = '%s -fno-strict-aliasing -D_FREEBSD_' % CXXFLAGS
 | 
			
		||||
	    OS_DEFINES     = '-D_FREEBSD_'
 | 
			
		||||
            SO_EXT         = '.so'
 | 
			
		||||
            LDFLAGS        = '%s -lrt' % LDFLAGS
 | 
			
		||||
            SLIBFLAGS      = '-shared'
 | 
			
		||||
            SLIBEXTRAFLAGS = '%s -lrt' % SLIBEXTRAFLAGS
 | 
			
		||||
        elif sysname[:6] ==  'CYGWIN':
 | 
			
		||||
            CXXFLAGS    = '%s -D_CYGWIN -fno-strict-aliasing' % CXXFLAGS
 | 
			
		||||
	    OS_DEFINES     = '-D_CYGWIN'
 | 
			
		||||
            SO_EXT      = '.dll'
 | 
			
		||||
            SLIBFLAGS   = '-shared'
 | 
			
		||||
        else:
 | 
			
		||||
| 
						 | 
				
			
			@ -1573,6 +1580,7 @@ def mk_config():
 | 
			
		|||
        config.write('SLINK_FLAGS=%s\n' % SLIBFLAGS)
 | 
			
		||||
        config.write('SLINK_EXTRA_FLAGS=%s\n' % SLIBEXTRAFLAGS)
 | 
			
		||||
        config.write('SLINK_OUT_FLAG=-o \n')
 | 
			
		||||
	config.write('OS_DEFINES=%s\n' % OS_DEFINES)
 | 
			
		||||
        if is_verbose():
 | 
			
		||||
            print('Host platform:  %s' % sysname)
 | 
			
		||||
            print('C++ Compiler:   %s' % CXX)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -373,7 +373,7 @@ extern "C" {
 | 
			
		|||
        scoped_anum_vector roots(_am);
 | 
			
		||||
        {
 | 
			
		||||
            cancel_eh<algebraic_numbers::manager> eh(_am);
 | 
			
		||||
            api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
            api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
            scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
 | 
			
		||||
            vector_var2anum v2a(as);
 | 
			
		||||
            _am.isolate_roots(_p, v2a, roots);
 | 
			
		||||
| 
						 | 
				
			
			@ -408,7 +408,7 @@ extern "C" {
 | 
			
		|||
        }
 | 
			
		||||
        {
 | 
			
		||||
            cancel_eh<algebraic_numbers::manager> eh(_am);
 | 
			
		||||
            api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
            api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
            scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
 | 
			
		||||
            vector_var2anum v2a(as);
 | 
			
		||||
            int r = _am.eval_sign_at(_p, v2a);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ extern "C" {
 | 
			
		|||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_mk_int_symbol(c, i);
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        if (i < 0 || (unsigned)i >= (SIZE_MAX >> PTR_ALIGNMENT)) {
 | 
			
		||||
        if (i < 0 || (size_t)i >= (SIZE_MAX >> PTR_ALIGNMENT)) {
 | 
			
		||||
            SET_ERROR_CODE(Z3_IOB);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -682,7 +682,7 @@ extern "C" {
 | 
			
		|||
        th_rewriter m_rw(m, p);
 | 
			
		||||
        expr_ref    result(m);
 | 
			
		||||
        cancel_eh<th_rewriter> eh(m_rw);
 | 
			
		||||
        api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
        api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
        {
 | 
			
		||||
            scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
 | 
			
		||||
            scoped_timer timer(timeout, &eh);
 | 
			
		||||
| 
						 | 
				
			
			@ -1072,6 +1072,16 @@ extern "C" {
 | 
			
		|||
            case OP_BV2INT:    return Z3_OP_BV2INT;
 | 
			
		||||
            case OP_CARRY:     return Z3_OP_CARRY;
 | 
			
		||||
            case OP_XOR3:      return Z3_OP_XOR3;
 | 
			
		||||
            case OP_BSMUL_NO_OVFL: 
 | 
			
		||||
            case OP_BUMUL_NO_OVFL:
 | 
			
		||||
            case OP_BSMUL_NO_UDFL:
 | 
			
		||||
            case OP_BSDIV_I:
 | 
			
		||||
            case OP_BUDIV_I:
 | 
			
		||||
            case OP_BSREM_I:
 | 
			
		||||
            case OP_BUREM_I:
 | 
			
		||||
            case OP_BSMOD_I:
 | 
			
		||||
 | 
			
		||||
                return Z3_OP_UNINTERPRETED;
 | 
			
		||||
            default:
 | 
			
		||||
                UNREACHABLE();
 | 
			
		||||
                return Z3_OP_UNINTERPRETED;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -121,10 +121,20 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
			
		|||
            unsigned sz = Z3_get_bv_sort_size(c, s);
 | 
			
		||||
            rational max_bound = power(rational(2), sz);
 | 
			
		||||
            Z3_ast bound = Z3_mk_numeral(c, max_bound.to_string().c_str(), int_s);
 | 
			
		||||
            Z3_ast pred = Z3_mk_bvslt(c, n, Z3_mk_int(c, 0, s));        
 | 
			
		||||
            Z3_inc_ref(c, bound);
 | 
			
		||||
            Z3_ast zero = Z3_mk_int(c, 0, s);
 | 
			
		||||
            Z3_inc_ref(c, zero);
 | 
			
		||||
            Z3_ast pred = Z3_mk_bvslt(c, n, zero);        
 | 
			
		||||
            Z3_inc_ref(c, pred);
 | 
			
		||||
            // if n <_sigend 0 then r - s^sz else r
 | 
			
		||||
            Z3_ast args[2] = { r, bound };
 | 
			
		||||
            Z3_ast res = Z3_mk_ite(c, pred, Z3_mk_sub(c, 2, args), r);
 | 
			
		||||
            Z3_ast sub = Z3_mk_sub(c, 2, args);
 | 
			
		||||
            Z3_inc_ref(c, sub);
 | 
			
		||||
            Z3_ast res = Z3_mk_ite(c, pred, sub, r);
 | 
			
		||||
            Z3_dec_ref(c, bound);
 | 
			
		||||
            Z3_dec_ref(c, pred);
 | 
			
		||||
            Z3_dec_ref(c, sub);
 | 
			
		||||
            Z3_dec_ref(c, zero);
 | 
			
		||||
            RETURN_Z3(res);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
| 
						 | 
				
			
			@ -156,7 +166,14 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
			
		|||
            SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
            return 0;
 | 
			
		||||
        }
 | 
			
		||||
        return Z3_mk_bvshl(c, Z3_mk_int64(c, 1, s), Z3_mk_int64(c, sz - 1, s));
 | 
			
		||||
        Z3_ast x = Z3_mk_int64(c, 1, s);
 | 
			
		||||
        Z3_inc_ref(c, x);
 | 
			
		||||
        Z3_ast y = Z3_mk_int64(c, sz - 1, s);
 | 
			
		||||
        Z3_inc_ref(c, y);
 | 
			
		||||
        Z3_ast result = Z3_mk_bvshl(c, x, y);
 | 
			
		||||
        Z3_dec_ref(c, x);
 | 
			
		||||
        Z3_dec_ref(c, y);
 | 
			
		||||
        return result;
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -177,17 +194,40 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        if (is_signed) {
 | 
			
		||||
            Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
 | 
			
		||||
            Z3_inc_ref(c, zero);
 | 
			
		||||
            Z3_ast r = Z3_mk_bvadd(c, t1, t2);
 | 
			
		||||
            Z3_ast args[2] = { Z3_mk_bvslt(c, zero, t1), Z3_mk_bvslt(c, zero, t2) };
 | 
			
		||||
            Z3_inc_ref(c, r);
 | 
			
		||||
            Z3_ast l1 = Z3_mk_bvslt(c, zero, t1);
 | 
			
		||||
            Z3_inc_ref(c, l1);
 | 
			
		||||
            Z3_ast l2 = Z3_mk_bvslt(c, zero, t2);
 | 
			
		||||
            Z3_inc_ref(c, l2);
 | 
			
		||||
            Z3_ast args[2] = { l1, l2 };
 | 
			
		||||
            Z3_ast args_pos = Z3_mk_and(c, 2, args);
 | 
			
		||||
            return Z3_mk_implies(c, args_pos, Z3_mk_bvslt(c, zero, r));
 | 
			
		||||
            Z3_inc_ref(c, args_pos);
 | 
			
		||||
            Z3_ast result = Z3_mk_implies(c, args_pos, Z3_mk_bvslt(c, zero, r));
 | 
			
		||||
            Z3_dec_ref(c, r);
 | 
			
		||||
            Z3_dec_ref(c, l1);
 | 
			
		||||
            Z3_dec_ref(c, l2);
 | 
			
		||||
            Z3_dec_ref(c, args_pos);
 | 
			
		||||
            Z3_dec_ref(c, zero);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            unsigned sz = Z3_get_bv_sort_size(c, Z3_get_sort(c, t1));
 | 
			
		||||
            t1 = Z3_mk_zero_ext(c, 1, t1);
 | 
			
		||||
            Z3_inc_ref(c, t1);
 | 
			
		||||
            t2 = Z3_mk_zero_ext(c, 1, t2);
 | 
			
		||||
            Z3_inc_ref(c, t2);
 | 
			
		||||
            Z3_ast r = Z3_mk_bvadd(c, t1, t2);
 | 
			
		||||
            return Z3_mk_eq(c, Z3_mk_extract(c, sz, sz, r), Z3_mk_int(c, 0, Z3_mk_bv_sort(c, 1)));
 | 
			
		||||
            Z3_inc_ref(c, r);
 | 
			
		||||
            Z3_ast ex = Z3_mk_extract(c, sz, sz, r);
 | 
			
		||||
            Z3_inc_ref(c, ex);
 | 
			
		||||
            Z3_ast result = Z3_mk_eq(c, ex, Z3_mk_int(c, 0, Z3_mk_bv_sort(c, 1)));
 | 
			
		||||
            Z3_dec_ref(c, t1);
 | 
			
		||||
            Z3_dec_ref(c, t2);
 | 
			
		||||
            Z3_dec_ref(c, ex);
 | 
			
		||||
            Z3_dec_ref(c, r);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -197,10 +237,26 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
			
		|||
        Z3_TRY;
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
 | 
			
		||||
        Z3_inc_ref(c, zero);
 | 
			
		||||
        Z3_ast r = Z3_mk_bvadd(c, t1, t2);
 | 
			
		||||
        Z3_ast args[2] = { Z3_mk_bvslt(c, t1, zero), Z3_mk_bvslt(c, t2, zero) };
 | 
			
		||||
        Z3_inc_ref(c, r);
 | 
			
		||||
        Z3_ast l1 = Z3_mk_bvslt(c, t1, zero);
 | 
			
		||||
        Z3_inc_ref(c, l1);
 | 
			
		||||
        Z3_ast l2 = Z3_mk_bvslt(c, t2, zero);
 | 
			
		||||
        Z3_inc_ref(c, l2);
 | 
			
		||||
        Z3_ast args[2] = { l1, l2 };
 | 
			
		||||
        Z3_ast args_neg = Z3_mk_and(c, 2, args);
 | 
			
		||||
        return Z3_mk_implies(c, args_neg, Z3_mk_bvslt(c, r, zero));
 | 
			
		||||
        Z3_inc_ref(c, args_neg);
 | 
			
		||||
        Z3_ast lt = Z3_mk_bvslt(c, r, zero);
 | 
			
		||||
        Z3_inc_ref(c, lt);
 | 
			
		||||
        Z3_ast result = Z3_mk_implies(c, args_neg, lt);
 | 
			
		||||
        Z3_dec_ref(c, lt);
 | 
			
		||||
        Z3_dec_ref(c, l1);
 | 
			
		||||
        Z3_dec_ref(c, l2);
 | 
			
		||||
        Z3_dec_ref(c, r);
 | 
			
		||||
        Z3_dec_ref(c, args_neg);
 | 
			
		||||
        Z3_dec_ref(c, zero);
 | 
			
		||||
        return result;
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -208,12 +264,28 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
			
		|||
    Z3_ast Z3_API Z3_mk_bvsub_no_overflow(__in Z3_context c, __in Z3_ast t1, __in Z3_ast t2) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        Z3_sort s = Z3_get_sort(c, t2);
 | 
			
		||||
        Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
 | 
			
		||||
        Z3_inc_ref(c, minus_t2);
 | 
			
		||||
        Z3_sort s = Z3_get_sort(c, t2);
 | 
			
		||||
        Z3_ast min = Z3_mk_bvsmin(c, s);
 | 
			
		||||
        return Z3_mk_ite(c, Z3_mk_eq(c, t2, min), 
 | 
			
		||||
                         Z3_mk_bvslt(c, t1, Z3_mk_int(c, 0, s)),
 | 
			
		||||
                         Z3_mk_bvadd_no_overflow(c, t1, minus_t2, true));
 | 
			
		||||
        Z3_inc_ref(c, min);
 | 
			
		||||
        Z3_ast x = Z3_mk_eq(c, t2, min);
 | 
			
		||||
        Z3_inc_ref(c, x);
 | 
			
		||||
        Z3_ast zero = Z3_mk_int(c, 0, s);
 | 
			
		||||
        Z3_inc_ref(c, zero);
 | 
			
		||||
        Z3_ast y = Z3_mk_bvslt(c, t1, zero);
 | 
			
		||||
        Z3_inc_ref(c, y);
 | 
			
		||||
        Z3_ast z = Z3_mk_bvadd_no_overflow(c, t1, minus_t2, true);
 | 
			
		||||
        Z3_inc_ref(c, z);
 | 
			
		||||
        Z3_ast result = Z3_mk_ite(c, x, y, z);
 | 
			
		||||
        mk_c(c)->save_ast_trail(to_app(result));
 | 
			
		||||
        Z3_dec_ref(c, minus_t2);
 | 
			
		||||
        Z3_dec_ref(c, min);
 | 
			
		||||
        Z3_dec_ref(c, x);
 | 
			
		||||
        Z3_dec_ref(c, y);
 | 
			
		||||
        Z3_dec_ref(c, z);
 | 
			
		||||
        Z3_dec_ref(c, zero);
 | 
			
		||||
        return result;
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -222,10 +294,19 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        if (is_signed) {
 | 
			
		||||
            Z3_ast zero = Z3_mk_int(c, 0, Z3_get_sort(c, t1));
 | 
			
		||||
            if (Z3_get_error_code(c) != Z3_OK) return 0;
 | 
			
		||||
            Z3_inc_ref(c, zero);
 | 
			
		||||
            Z3_ast minus_t2 = Z3_mk_bvneg(c, t2);
 | 
			
		||||
            if (Z3_get_error_code(c) != Z3_OK) return 0;
 | 
			
		||||
            return Z3_mk_implies(c, Z3_mk_bvslt(c, zero, t2), Z3_mk_bvadd_no_underflow(c, t1, minus_t2));
 | 
			
		||||
            Z3_inc_ref(c, minus_t2);
 | 
			
		||||
            Z3_ast x = Z3_mk_bvslt(c, zero, t2);
 | 
			
		||||
            Z3_inc_ref(c, x);
 | 
			
		||||
            Z3_ast y = Z3_mk_bvadd_no_underflow(c, t1, minus_t2);
 | 
			
		||||
            Z3_inc_ref(c, y);
 | 
			
		||||
            Z3_ast result = Z3_mk_implies(c, x, y);
 | 
			
		||||
            Z3_dec_ref(c, zero);
 | 
			
		||||
            Z3_dec_ref(c, minus_t2);
 | 
			
		||||
            Z3_dec_ref(c, x);
 | 
			
		||||
            Z3_dec_ref(c, y);
 | 
			
		||||
            return result;
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            return Z3_mk_bvule(c, t2, t1);
 | 
			
		||||
| 
						 | 
				
			
			@ -267,12 +348,24 @@ Z3_ast Z3_API NAME(Z3_context c, unsigned i, Z3_ast n) {                \
 | 
			
		|||
        Z3_TRY;
 | 
			
		||||
        RESET_ERROR_CODE();
 | 
			
		||||
        Z3_sort s = Z3_get_sort(c, t1);
 | 
			
		||||
        if (Z3_get_error_code(c) != Z3_OK) return 0;
 | 
			
		||||
        Z3_ast min = Z3_mk_bvmsb(c, s);
 | 
			
		||||
        if (Z3_get_error_code(c) != Z3_OK) return 0;
 | 
			
		||||
        Z3_ast args[2] = { Z3_mk_eq(c, t1, min),
 | 
			
		||||
                           Z3_mk_eq(c, t2, Z3_mk_int(c, -1, s)) };
 | 
			
		||||
        return Z3_mk_not(c, Z3_mk_and(c, 2, args));
 | 
			
		||||
        Z3_inc_ref(c, min);
 | 
			
		||||
        Z3_ast x = Z3_mk_eq(c, t1, min);
 | 
			
		||||
        Z3_inc_ref(c, x);
 | 
			
		||||
        Z3_ast y = Z3_mk_int(c, -1, s);
 | 
			
		||||
        Z3_inc_ref(c, y);
 | 
			
		||||
        Z3_ast z = Z3_mk_eq(c, t2, y);
 | 
			
		||||
        Z3_inc_ref(c, z);
 | 
			
		||||
        Z3_ast args[2] = { x, z };
 | 
			
		||||
        Z3_ast u = Z3_mk_and(c, 2, args);
 | 
			
		||||
        Z3_inc_ref(c, u);
 | 
			
		||||
        Z3_ast result = Z3_mk_not(c, u);
 | 
			
		||||
        Z3_dec_ref(c, min);
 | 
			
		||||
        Z3_dec_ref(c, x);
 | 
			
		||||
        Z3_dec_ref(c, y);
 | 
			
		||||
        Z3_dec_ref(c, z);
 | 
			
		||||
        Z3_dec_ref(c, u);
 | 
			
		||||
        return result;
 | 
			
		||||
        Z3_CATCH_RETURN(0);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -139,7 +139,7 @@ namespace api {
 | 
			
		|||
            if (m_interruptable)
 | 
			
		||||
                (*m_interruptable)();
 | 
			
		||||
            m().set_cancel(true);
 | 
			
		||||
            if (m_rcf_manager.get() == 0)
 | 
			
		||||
            if (m_rcf_manager.get() != 0)
 | 
			
		||||
                m_rcf_manager->set_cancel(true);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,7 +18,6 @@ Revision History:
 | 
			
		|||
#include"api_datalog.h"
 | 
			
		||||
#include"api_context.h"
 | 
			
		||||
#include"api_util.h"
 | 
			
		||||
#include"dl_context.h"
 | 
			
		||||
#include"ast_pp.h"
 | 
			
		||||
#include"api_ast_vector.h"
 | 
			
		||||
#include"api_log_macros.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -29,104 +28,126 @@ Revision History:
 | 
			
		|||
#include"dl_cmds.h"
 | 
			
		||||
#include"cmd_context.h"
 | 
			
		||||
#include"smt2parser.h"
 | 
			
		||||
#include"dl_context.h"
 | 
			
		||||
#include"dl_register_engine.h"
 | 
			
		||||
#include"dl_external_relation.h"
 | 
			
		||||
#include"dl_decl_plugin.h"
 | 
			
		||||
#include"rel_context.h"
 | 
			
		||||
 | 
			
		||||
namespace api {
 | 
			
		||||
 | 
			
		||||
    fixedpoint_context::fixedpoint_context(ast_manager& m, smt_params& p) : 
 | 
			
		||||
        m_state(0), 
 | 
			
		||||
        m_reduce_app(0), 
 | 
			
		||||
        m_reduce_assign(0), 
 | 
			
		||||
        m_context(m, p),
 | 
			
		||||
        m_trail(m) {}
 | 
			
		||||
    class fixedpoint_context : public datalog::external_relation_context {
 | 
			
		||||
        void *                       m_state;
 | 
			
		||||
        reduce_app_callback_fptr     m_reduce_app;
 | 
			
		||||
        reduce_assign_callback_fptr  m_reduce_assign;
 | 
			
		||||
        datalog::register_engine     m_register_engine;
 | 
			
		||||
        datalog::context             m_context;    
 | 
			
		||||
        ast_ref_vector               m_trail;        
 | 
			
		||||
    public:
 | 
			
		||||
        fixedpoint_context(ast_manager& m, smt_params& p): 
 | 
			
		||||
            m_state(0), 
 | 
			
		||||
            m_reduce_app(0), 
 | 
			
		||||
            m_reduce_assign(0), 
 | 
			
		||||
            m_context(m, m_register_engine, p),
 | 
			
		||||
            m_trail(m) {}
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    void fixedpoint_context::set_state(void* state) {
 | 
			
		||||
        SASSERT(!m_state);
 | 
			
		||||
        m_state = state;
 | 
			
		||||
        symbol name("datalog_relation");
 | 
			
		||||
        ast_manager& m = m_context.get_manager();
 | 
			
		||||
        if (!m.has_plugin(name)) {
 | 
			
		||||
            m.register_plugin(name, alloc(datalog::dl_decl_plugin));
 | 
			
		||||
        }        
 | 
			
		||||
        datalog::relation_manager& r = m_context.get_rel_context().get_rmanager();
 | 
			
		||||
        r.register_plugin(alloc(datalog::external_relation_plugin, *this, r));
 | 
			
		||||
    }        
 | 
			
		||||
    
 | 
			
		||||
    void fixedpoint_context::reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) {
 | 
			
		||||
        expr* r = 0;
 | 
			
		||||
        if (m_reduce_app) {
 | 
			
		||||
            m_reduce_app(m_state, f, num_args, args, &r);
 | 
			
		||||
            result = r;
 | 
			
		||||
            m_trail.push_back(f);
 | 
			
		||||
            for (unsigned i = 0; i < num_args; ++i) {
 | 
			
		||||
                m_trail.push_back(args[i]);
 | 
			
		||||
            }
 | 
			
		||||
            m_trail.push_back(r);
 | 
			
		||||
        }
 | 
			
		||||
        // allow fallthrough.
 | 
			
		||||
        if (r == 0) {
 | 
			
		||||
        virtual ~fixedpoint_context() {}
 | 
			
		||||
        family_id get_family_id() const { return const_cast<datalog::context&>(m_context).get_decl_util().get_family_id(); }
 | 
			
		||||
        void set_state(void* state) {
 | 
			
		||||
            SASSERT(!m_state);
 | 
			
		||||
            m_state = state;
 | 
			
		||||
            symbol name("datalog_relation");
 | 
			
		||||
            ast_manager& m = m_context.get_manager();
 | 
			
		||||
            result = m.mk_app(f, num_args, args);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    // overwrite terms passed in outs vector with values computed by function.
 | 
			
		||||
    void fixedpoint_context::reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) {
 | 
			
		||||
        if (m_reduce_assign) {
 | 
			
		||||
            m_trail.push_back(f);
 | 
			
		||||
            for (unsigned i = 0; i < num_args; ++i) {
 | 
			
		||||
                m_trail.push_back(args[i]);
 | 
			
		||||
            if (!m.has_plugin(name)) {
 | 
			
		||||
                m.register_plugin(name, alloc(datalog::dl_decl_plugin));
 | 
			
		||||
            }        
 | 
			
		||||
            datalog::rel_context_base* rel = m_context.get_rel_context();
 | 
			
		||||
            if (rel) {
 | 
			
		||||
                datalog::relation_manager& r = rel->get_rmanager();
 | 
			
		||||
                r.register_plugin(alloc(datalog::external_relation_plugin, *this, r));
 | 
			
		||||
            }
 | 
			
		||||
            m_reduce_assign(m_state, f, num_args, args, num_out, outs);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    void fixedpoint_context::add_rule(expr* rule, symbol const& name) {
 | 
			
		||||
        m_context.add_rule(rule, name);
 | 
			
		||||
    }   
 | 
			
		||||
 | 
			
		||||
    void fixedpoint_context::update_rule(expr* rule, symbol const& name) {
 | 
			
		||||
        m_context.update_rule(rule, name);
 | 
			
		||||
    }   
 | 
			
		||||
 | 
			
		||||
    void fixedpoint_context::add_table_fact(func_decl* r, unsigned num_args, unsigned args[]) {
 | 
			
		||||
        m_context.add_table_fact(r, num_args, args);
 | 
			
		||||
    }   
 | 
			
		||||
 | 
			
		||||
    unsigned fixedpoint_context::get_num_levels(func_decl* pred) {
 | 
			
		||||
        return m_context.get_num_levels(pred);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    expr_ref fixedpoint_context::get_cover_delta(int level, func_decl* pred) {
 | 
			
		||||
        return m_context.get_cover_delta(level, pred);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void fixedpoint_context::add_cover(int level, func_decl* pred, expr* predicate) {
 | 
			
		||||
        m_context.add_cover(level, pred, predicate);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    std::string fixedpoint_context::get_last_status() {
 | 
			
		||||
        datalog::execution_result status = m_context.get_status();
 | 
			
		||||
        switch(status) {
 | 
			
		||||
        case datalog::INPUT_ERROR:
 | 
			
		||||
            return "input error";        
 | 
			
		||||
        case datalog::OK:
 | 
			
		||||
            return "ok";
 | 
			
		||||
        case datalog::TIMEOUT:            
 | 
			
		||||
            return "timeout";
 | 
			
		||||
        default:
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
            return "unknown";
 | 
			
		||||
        void set_reduce_app(reduce_app_callback_fptr f) { 
 | 
			
		||||
            m_reduce_app = f; 
 | 
			
		||||
        }
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    std::string fixedpoint_context::to_string(unsigned num_queries, expr*const* queries) {
 | 
			
		||||
        std::stringstream str;
 | 
			
		||||
        m_context.display_smt2(num_queries, queries, str);
 | 
			
		||||
        return str.str();
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
        void set_reduce_assign(reduce_assign_callback_fptr f) { 
 | 
			
		||||
            m_reduce_assign = f; 
 | 
			
		||||
        }
 | 
			
		||||
        virtual void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result) {
 | 
			
		||||
            expr* r = 0;
 | 
			
		||||
            if (m_reduce_app) {
 | 
			
		||||
                m_reduce_app(m_state, f, num_args, args, &r);
 | 
			
		||||
                result = r;
 | 
			
		||||
                m_trail.push_back(f);
 | 
			
		||||
                for (unsigned i = 0; i < num_args; ++i) {
 | 
			
		||||
                    m_trail.push_back(args[i]);
 | 
			
		||||
                }
 | 
			
		||||
                m_trail.push_back(r);
 | 
			
		||||
            }
 | 
			
		||||
            // allow fallthrough.
 | 
			
		||||
            if (r == 0) {
 | 
			
		||||
                ast_manager& m = m_context.get_manager();
 | 
			
		||||
                result = m.mk_app(f, num_args, args);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        virtual void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs) {
 | 
			
		||||
            if (m_reduce_assign) {
 | 
			
		||||
                m_trail.push_back(f);
 | 
			
		||||
                for (unsigned i = 0; i < num_args; ++i) {
 | 
			
		||||
                    m_trail.push_back(args[i]);
 | 
			
		||||
                }
 | 
			
		||||
                m_reduce_assign(m_state, f, num_args, args, num_out, outs);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        datalog::context& ctx() { return m_context; }
 | 
			
		||||
        void add_rule(expr* rule, symbol const& name) {
 | 
			
		||||
            m_context.add_rule(rule, name);
 | 
			
		||||
        }
 | 
			
		||||
        void update_rule(expr* rule, symbol const& name) {
 | 
			
		||||
            m_context.update_rule(rule, name);
 | 
			
		||||
        }
 | 
			
		||||
        void add_table_fact(func_decl* r, unsigned num_args, unsigned args[]) {
 | 
			
		||||
            m_context.add_table_fact(r, num_args, args);
 | 
			
		||||
        }
 | 
			
		||||
        std::string get_last_status() {
 | 
			
		||||
            datalog::execution_result status = m_context.get_status();
 | 
			
		||||
            switch(status) {
 | 
			
		||||
            case datalog::INPUT_ERROR:
 | 
			
		||||
                return "input error";        
 | 
			
		||||
            case datalog::OK:
 | 
			
		||||
                return "ok";
 | 
			
		||||
            case datalog::TIMEOUT:            
 | 
			
		||||
                return "timeout";
 | 
			
		||||
            case datalog::APPROX:
 | 
			
		||||
                return "approximated";
 | 
			
		||||
            default:
 | 
			
		||||
                UNREACHABLE();
 | 
			
		||||
                return "unknown";
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        std::string to_string(unsigned num_queries, expr*const* queries) {
 | 
			
		||||
            std::stringstream str;
 | 
			
		||||
            m_context.display_smt2(num_queries, queries, str);
 | 
			
		||||
            return str.str();
 | 
			
		||||
        }
 | 
			
		||||
        void cancel() { 
 | 
			
		||||
            m_context.cancel(); 
 | 
			
		||||
        }
 | 
			
		||||
        void reset_cancel() { 
 | 
			
		||||
            m_context.reset_cancel(); 
 | 
			
		||||
        }
 | 
			
		||||
        unsigned get_num_levels(func_decl* pred) {
 | 
			
		||||
            return m_context.get_num_levels(pred);
 | 
			
		||||
        }
 | 
			
		||||
        expr_ref get_cover_delta(int level, func_decl* pred) {
 | 
			
		||||
            return m_context.get_cover_delta(level, pred);
 | 
			
		||||
        }
 | 
			
		||||
        void add_cover(int level, func_decl* pred, expr* predicate) {
 | 
			
		||||
            m_context.add_cover(level, pred, predicate);
 | 
			
		||||
        }
 | 
			
		||||
        void collect_param_descrs(param_descrs & p) { m_context.collect_params(p); }
 | 
			
		||||
        void updt_params(params_ref const& p) { m_context.updt_params(p); }
 | 
			
		||||
    };         
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
extern "C" {
 | 
			
		||||
| 
						 | 
				
			
			@ -266,7 +287,7 @@ extern "C" {
 | 
			
		|||
        lbool r = l_undef;
 | 
			
		||||
        cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
 | 
			
		||||
        unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
 | 
			
		||||
        api::context::set_interruptable(*(mk_c(c)), eh);        
 | 
			
		||||
        api::context::set_interruptable si(*(mk_c(c)), eh);        
 | 
			
		||||
        {
 | 
			
		||||
            scoped_timer timer(timeout, &eh);
 | 
			
		||||
            try {
 | 
			
		||||
| 
						 | 
				
			
			@ -291,7 +312,7 @@ extern "C" {
 | 
			
		|||
        lbool r = l_undef;
 | 
			
		||||
        unsigned timeout = to_fixedpoint(d)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
 | 
			
		||||
        cancel_eh<api::fixedpoint_context> eh(*to_fixedpoint_ref(d));
 | 
			
		||||
        api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
        api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
        {
 | 
			
		||||
            scoped_timer timer(timeout, &eh);
 | 
			
		||||
            try {
 | 
			
		||||
| 
						 | 
				
			
			@ -358,7 +379,7 @@ extern "C" {
 | 
			
		|||
            v->m_ast_vector.push_back(coll.m_queries[i].get());
 | 
			
		||||
        }
 | 
			
		||||
        for (unsigned i = 0; i < coll.m_rels.size(); ++i) {
 | 
			
		||||
            to_fixedpoint_ref(d)->ctx().register_predicate(coll.m_rels[i].get());
 | 
			
		||||
            to_fixedpoint_ref(d)->ctx().register_predicate(coll.m_rels[i].get(), true);
 | 
			
		||||
        }
 | 
			
		||||
        for (unsigned i = 0; i < coll.m_rules.size(); ++i) {
 | 
			
		||||
            to_fixedpoint_ref(d)->add_rule(coll.m_rules[i].get(), coll.m_names[i]);
 | 
			
		||||
| 
						 | 
				
			
			@ -415,7 +436,7 @@ extern "C" {
 | 
			
		|||
    void Z3_API Z3_fixedpoint_register_relation(Z3_context c,Z3_fixedpoint d, Z3_func_decl f) {
 | 
			
		||||
        Z3_TRY;
 | 
			
		||||
        LOG_Z3_fixedpoint_register_relation(c, d, f);
 | 
			
		||||
        to_fixedpoint_ref(d)->ctx().register_predicate(to_func_decl(f));
 | 
			
		||||
        to_fixedpoint_ref(d)->ctx().register_predicate(to_func_decl(f), true);
 | 
			
		||||
        Z3_CATCH;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,48 +22,14 @@ Revision History:
 | 
			
		|||
#include"z3.h"
 | 
			
		||||
#include"ast.h"
 | 
			
		||||
#include"smt_params.h"
 | 
			
		||||
#include"dl_external_relation.h"
 | 
			
		||||
#include"dl_decl_plugin.h"
 | 
			
		||||
#include"smt_kernel.h"
 | 
			
		||||
#include"api_util.h"
 | 
			
		||||
#include"dl_context.h"
 | 
			
		||||
 | 
			
		||||
typedef void (*reduce_app_callback_fptr)(void*, func_decl*, unsigned, expr*const*, expr**);
 | 
			
		||||
typedef void (*reduce_assign_callback_fptr)(void*, func_decl*, unsigned, expr*const*, unsigned, expr*const*);
 | 
			
		||||
 | 
			
		||||
namespace api {
 | 
			
		||||
    
 | 
			
		||||
    class fixedpoint_context : public datalog::external_relation_context {
 | 
			
		||||
        void *                       m_state;
 | 
			
		||||
        reduce_app_callback_fptr     m_reduce_app;
 | 
			
		||||
        reduce_assign_callback_fptr  m_reduce_assign;
 | 
			
		||||
        datalog::context             m_context;    
 | 
			
		||||
        ast_ref_vector               m_trail;        
 | 
			
		||||
    public:
 | 
			
		||||
        fixedpoint_context(ast_manager& m, smt_params& p);
 | 
			
		||||
        virtual ~fixedpoint_context() {}
 | 
			
		||||
        family_id get_family_id() const { return const_cast<datalog::context&>(m_context).get_decl_util().get_family_id(); }
 | 
			
		||||
        void set_state(void* state);
 | 
			
		||||
        void set_reduce_app(reduce_app_callback_fptr f) { m_reduce_app = f; }
 | 
			
		||||
        void set_reduce_assign(reduce_assign_callback_fptr f) { m_reduce_assign = f; }
 | 
			
		||||
        virtual void reduce(func_decl* f, unsigned num_args, expr * const* args, expr_ref& result);
 | 
			
		||||
        virtual void reduce_assign(func_decl* f, unsigned num_args, expr * const* args, unsigned num_out, expr* const* outs);
 | 
			
		||||
        datalog::context& ctx() { return m_context; }
 | 
			
		||||
        void add_rule(expr* rule, symbol const& name);
 | 
			
		||||
        void update_rule(expr* rule, symbol const& name);
 | 
			
		||||
        void add_table_fact(func_decl* r, unsigned num_args, unsigned args[]);
 | 
			
		||||
        std::string get_last_status();
 | 
			
		||||
        std::string to_string(unsigned num_queries, expr*const* queries);
 | 
			
		||||
        void cancel() { m_context.cancel(); }
 | 
			
		||||
        void reset_cancel() { m_context.reset_cancel(); }
 | 
			
		||||
 | 
			
		||||
        unsigned get_num_levels(func_decl* pred);
 | 
			
		||||
        expr_ref get_cover_delta(int level, func_decl* pred);
 | 
			
		||||
        void add_cover(int level, func_decl* pred, expr* predicate);
 | 
			
		||||
        void collect_param_descrs(param_descrs & p) { m_context.collect_params(p); }
 | 
			
		||||
        void updt_params(params_ref const& p) { m_context.updt_params(p); }
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
    class fixedpoint_context;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -67,7 +67,7 @@ extern "C" {
 | 
			
		|||
            expr_ref _r(mk_c(c)->m());
 | 
			
		||||
            {
 | 
			
		||||
                cancel_eh<polynomial::manager> eh(pm);
 | 
			
		||||
                api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
                api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
                scoped_timer timer(mk_c(c)->params().m_timeout, &eh);
 | 
			
		||||
                pm.psc_chain(_p, _q, v_x, rs);
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -165,7 +165,10 @@ extern "C" {
 | 
			
		|||
        }
 | 
			
		||||
        for (unsigned i = 0; i < num_bound; ++i) {
 | 
			
		||||
            app* a = to_app(bound[i]);
 | 
			
		||||
            SASSERT(a->get_kind() == AST_APP);
 | 
			
		||||
            if (a->get_kind() != AST_APP) {
 | 
			
		||||
                SET_ERROR_CODE(Z3_INVALID_ARG);
 | 
			
		||||
                RETURN_Z3(0);
 | 
			
		||||
            }
 | 
			
		||||
            symbol s(to_app(a)->get_decl()->get_name());
 | 
			
		||||
            names.push_back(of_symbol(s));
 | 
			
		||||
            types.push_back(of_sort(mk_c(c)->m().get_sort(a)));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -243,7 +243,7 @@ extern "C" {
 | 
			
		|||
        unsigned timeout     = to_solver(s)->m_params.get_uint("timeout", mk_c(c)->get_timeout());
 | 
			
		||||
        bool     use_ctrl_c  = to_solver(s)->m_params.get_bool("ctrl_c", false);
 | 
			
		||||
        cancel_eh<solver> eh(*to_solver_ref(s));
 | 
			
		||||
        api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
        api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
        lbool result;
 | 
			
		||||
        {
 | 
			
		||||
            scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -73,7 +73,7 @@ extern "C" {
 | 
			
		|||
        RESET_ERROR_CODE();
 | 
			
		||||
        CHECK_SEARCHING(c);
 | 
			
		||||
        cancel_eh<smt::kernel> eh(mk_c(c)->get_smt_kernel());
 | 
			
		||||
        api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
        api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
        flet<bool> _model(mk_c(c)->fparams().m_model, true);
 | 
			
		||||
        lbool result;
 | 
			
		||||
        try {
 | 
			
		||||
| 
						 | 
				
			
			@ -123,7 +123,7 @@ extern "C" {
 | 
			
		|||
        expr * const* _assumptions = to_exprs(assumptions);
 | 
			
		||||
        flet<bool> _model(mk_c(c)->fparams().m_model, true);
 | 
			
		||||
        cancel_eh<smt::kernel> eh(mk_c(c)->get_smt_kernel());
 | 
			
		||||
        api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
        api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
        lbool result;
 | 
			
		||||
        result = mk_c(c)->get_smt_kernel().check(num_assumptions, _assumptions);
 | 
			
		||||
        if (result != l_false && m) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -410,7 +410,7 @@ extern "C" {
 | 
			
		|||
        
 | 
			
		||||
        to_tactic_ref(t)->updt_params(p);
 | 
			
		||||
 | 
			
		||||
        api::context::set_interruptable(*(mk_c(c)), eh);
 | 
			
		||||
        api::context::set_interruptable si(*(mk_c(c)), eh);
 | 
			
		||||
        {
 | 
			
		||||
            scoped_ctrl_c ctrlc(eh, false, use_ctrl_c);
 | 
			
		||||
            scoped_timer timer(timeout, &eh);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -29,7 +29,6 @@ Revision History:
 | 
			
		|||
#define Z3_CATCH_RETURN_NO_HANDLE(VAL) } catch (z3_exception &) { return VAL; }
 | 
			
		||||
 | 
			
		||||
#define CHECK_REF_COUNT(a) (reinterpret_cast<ast const*>(a)->get_ref_count() > 0)
 | 
			
		||||
#define VALIDATE(a) SASSERT(!a || CHECK_REF_COUNT(a))
 | 
			
		||||
 | 
			
		||||
namespace api {
 | 
			
		||||
    // Generic wrapper for ref-count objects exposed by the API
 | 
			
		||||
| 
						 | 
				
			
			@ -44,30 +43,30 @@ namespace api {
 | 
			
		|||
    };
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
inline ast * to_ast(Z3_ast a) { VALIDATE(a); return reinterpret_cast<ast *>(a); }
 | 
			
		||||
inline ast * to_ast(Z3_ast a) { return reinterpret_cast<ast *>(a); }
 | 
			
		||||
inline Z3_ast of_ast(ast* a) { return reinterpret_cast<Z3_ast>(a); }
 | 
			
		||||
 | 
			
		||||
inline expr * to_expr(Z3_ast a) { VALIDATE(a); return reinterpret_cast<expr*>(a); }
 | 
			
		||||
inline expr * to_expr(Z3_ast a) { return reinterpret_cast<expr*>(a); }
 | 
			
		||||
inline Z3_ast of_expr(expr* e) { return reinterpret_cast<Z3_ast>(e); }
 | 
			
		||||
 | 
			
		||||
inline expr * const * to_exprs(Z3_ast const* a) { return reinterpret_cast<expr* const*>(a); }
 | 
			
		||||
inline Z3_ast * const * of_exprs(expr* const* e) { return reinterpret_cast<Z3_ast* const*>(e); }
 | 
			
		||||
 | 
			
		||||
inline app * to_app(Z3_app a) { VALIDATE(a); return reinterpret_cast<app*>(a); }
 | 
			
		||||
inline app * to_app(Z3_ast a) { VALIDATE(a); return reinterpret_cast<app*>(a); }
 | 
			
		||||
inline app * to_app(Z3_app a) { return reinterpret_cast<app*>(a); }
 | 
			
		||||
inline app * to_app(Z3_ast a) { return reinterpret_cast<app*>(a); }
 | 
			
		||||
inline Z3_app of_app(app* a) { return reinterpret_cast<Z3_app>(a); }
 | 
			
		||||
 | 
			
		||||
inline app * const* to_apps(Z3_ast const* a) { VALIDATE(a); return reinterpret_cast<app * const*>(a); }
 | 
			
		||||
inline app * const* to_apps(Z3_ast const* a) { return reinterpret_cast<app * const*>(a); }
 | 
			
		||||
 | 
			
		||||
inline ast * const * to_asts(Z3_ast const* a) { return reinterpret_cast<ast* const*>(a); }
 | 
			
		||||
 | 
			
		||||
inline sort * to_sort(Z3_sort a) { VALIDATE(a); return reinterpret_cast<sort*>(a); }
 | 
			
		||||
inline sort * to_sort(Z3_sort a) { return reinterpret_cast<sort*>(a); }
 | 
			
		||||
inline Z3_sort of_sort(sort* s) { return reinterpret_cast<Z3_sort>(s); }
 | 
			
		||||
 | 
			
		||||
inline sort * const *  to_sorts(Z3_sort const* a) { return reinterpret_cast<sort* const*>(a); }
 | 
			
		||||
inline Z3_sort const * of_sorts(sort* const* s) { return reinterpret_cast<Z3_sort const*>(s); }
 | 
			
		||||
 | 
			
		||||
inline func_decl * to_func_decl(Z3_func_decl a) { VALIDATE(a); return reinterpret_cast<func_decl*>(a); }
 | 
			
		||||
inline func_decl * to_func_decl(Z3_func_decl a) { return reinterpret_cast<func_decl*>(a); }
 | 
			
		||||
inline Z3_func_decl of_func_decl(func_decl* f) { return reinterpret_cast<Z3_func_decl>(f); }
 | 
			
		||||
 | 
			
		||||
inline func_decl * const * to_func_decls(Z3_func_decl const* f) { return reinterpret_cast<func_decl*const*>(f); }
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +74,7 @@ inline func_decl * const * to_func_decls(Z3_func_decl const* f) { return reinter
 | 
			
		|||
inline symbol to_symbol(Z3_symbol s) { return symbol::mk_symbol_from_c_ptr(reinterpret_cast<void*>(s)); }
 | 
			
		||||
inline Z3_symbol of_symbol(symbol s) { return reinterpret_cast<Z3_symbol>(const_cast<void*>(s.c_ptr())); }
 | 
			
		||||
 | 
			
		||||
inline Z3_pattern of_pattern(ast* a) { VALIDATE(a); return reinterpret_cast<Z3_pattern>(a); }
 | 
			
		||||
inline Z3_pattern of_pattern(ast* a) { return reinterpret_cast<Z3_pattern>(a); }
 | 
			
		||||
inline app* to_pattern(Z3_pattern p) { return reinterpret_cast<app*>(p); }
 | 
			
		||||
 | 
			
		||||
inline Z3_lbool of_lbool(lbool b) { return static_cast<Z3_lbool>(b); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -204,6 +204,8 @@ namespace z3 {
 | 
			
		|||
        
 | 
			
		||||
        func_decl function(symbol const & name, unsigned arity, sort const * domain, sort const & range);
 | 
			
		||||
        func_decl function(char const * name, unsigned arity, sort const * domain, sort const & range);
 | 
			
		||||
        func_decl function(symbol const&  name, sort_vector const& domain, sort const& range);
 | 
			
		||||
        func_decl function(char const * name, sort_vector const& domain, sort const& range);
 | 
			
		||||
        func_decl function(char const * name, sort const & domain, sort const & range);
 | 
			
		||||
        func_decl function(char const * name, sort const & d1, sort const & d2, sort const & range);
 | 
			
		||||
        func_decl function(char const * name, sort const & d1, sort const & d2, sort const & d3, sort const & range);
 | 
			
		||||
| 
						 | 
				
			
			@ -249,6 +251,8 @@ namespace z3 {
 | 
			
		|||
        array & operator=(array const & s);
 | 
			
		||||
    public:
 | 
			
		||||
        array(unsigned sz):m_size(sz) { m_array = new T[sz]; }
 | 
			
		||||
        template<typename T2>
 | 
			
		||||
        array(ast_vector_tpl<T2> const & v);
 | 
			
		||||
        ~array() { delete[] m_array; }
 | 
			
		||||
        unsigned size() const { return m_size; }
 | 
			
		||||
        T & operator[](int i) { assert(0 <= i); assert(static_cast<unsigned>(i) < m_size); return m_array[i]; }
 | 
			
		||||
| 
						 | 
				
			
			@ -427,6 +431,7 @@ namespace z3 {
 | 
			
		|||
 | 
			
		||||
        expr operator()() const;
 | 
			
		||||
        expr operator()(unsigned n, expr const * args) const;
 | 
			
		||||
        expr operator()(expr_vector const& v) const;
 | 
			
		||||
        expr operator()(expr const & a) const;
 | 
			
		||||
        expr operator()(int a) const;
 | 
			
		||||
        expr operator()(expr const & a1, expr const & a2) const;
 | 
			
		||||
| 
						 | 
				
			
			@ -872,7 +877,18 @@ namespace z3 {
 | 
			
		|||
           \brief Return a simplified version of this expression. The parameter \c p is a set of parameters for the Z3 simplifier.
 | 
			
		||||
        */
 | 
			
		||||
        expr simplify(params const & p) const { Z3_ast r = Z3_simplify_ex(ctx(), m_ast, p); check_error(); return expr(ctx(), r); }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Apply substitution. Replace src expressions by dst.
 | 
			
		||||
        */
 | 
			
		||||
        expr substitute(expr_vector const& src, expr_vector const& dst); 
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Apply substitution. Replace bound variables by expressions.
 | 
			
		||||
        */
 | 
			
		||||
        expr substitute(expr_vector const& dst);
 | 
			
		||||
 | 
			
		||||
   };
 | 
			
		||||
    
 | 
			
		||||
    /**                                        
 | 
			
		||||
       \brief Wraps a Z3_ast as an expr object. It also checks for errors.
 | 
			
		||||
| 
						 | 
				
			
			@ -928,49 +944,6 @@ namespace z3 {
 | 
			
		|||
    inline expr udiv(expr const & a, int b) { return udiv(a, a.ctx().num_val(b, a.get_sort())); }
 | 
			
		||||
    inline expr udiv(int a, expr const & b) { return udiv(b.ctx().num_val(a, b.get_sort()), b); }
 | 
			
		||||
 | 
			
		||||
    // Basic functions for creating quantified formulas.
 | 
			
		||||
    // The C API should be used for creating quantifiers with patterns, weights, many variables, etc.
 | 
			
		||||
    inline expr forall(expr const & x, expr const & b) {
 | 
			
		||||
        check_context(x, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr forall(expr const & x1, expr const & x2, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x, expr const & b) {
 | 
			
		||||
        check_context(x, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x1, expr const & x2, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    template<typename T> class cast_ast;
 | 
			
		||||
 | 
			
		||||
    template<> class cast_ast<ast> {
 | 
			
		||||
| 
						 | 
				
			
			@ -1032,6 +1005,67 @@ namespace z3 {
 | 
			
		|||
        friend std::ostream & operator<<(std::ostream & out, ast_vector_tpl const & v) { out << Z3_ast_vector_to_string(v.ctx(), v); return out; }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    template<typename T>
 | 
			
		||||
    template<typename T2>
 | 
			
		||||
    array<T>::array(ast_vector_tpl<T2> const & v) {
 | 
			
		||||
        m_array = new T[v.size()];
 | 
			
		||||
        m_size  = v.size();
 | 
			
		||||
        for (unsigned i = 0; i < m_size; i++) {
 | 
			
		||||
            m_array[i] = v[i];
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Basic functions for creating quantified formulas.
 | 
			
		||||
    // The C API should be used for creating quantifiers with patterns, weights, many variables, etc.
 | 
			
		||||
    inline expr forall(expr const & x, expr const & b) {
 | 
			
		||||
        check_context(x, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr forall(expr const & x1, expr const & x2, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr forall(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr forall(expr_vector const & xs, expr const & b) {
 | 
			
		||||
        array<Z3_app> vars(xs);  
 | 
			
		||||
        Z3_ast r = Z3_mk_forall_const(b.ctx(), 0, vars.size(), vars.ptr(), 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x, expr const & b) {
 | 
			
		||||
        check_context(x, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 1, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x1, expr const & x2, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2}; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 2, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 3, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr const & x1, expr const & x2, expr const & x3, expr const & x4, expr const & b) {
 | 
			
		||||
        check_context(x1, b); check_context(x2, b); check_context(x3, b); check_context(x4, b);
 | 
			
		||||
        Z3_app vars[] = {(Z3_app) x1, (Z3_app) x2, (Z3_app) x3, (Z3_app) x4 }; 
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, 4, vars, 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    inline expr exists(expr_vector const & xs, expr const & b) {
 | 
			
		||||
        array<Z3_app> vars(xs);  
 | 
			
		||||
        Z3_ast r = Z3_mk_exists_const(b.ctx(), 0, vars.size(), vars.ptr(), 0, 0, b); b.check_error(); return expr(b.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    class func_entry : public object {
 | 
			
		||||
        Z3_func_entry m_entry;
 | 
			
		||||
        void init(Z3_func_entry e) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1274,7 +1308,7 @@ namespace z3 {
 | 
			
		|||
        expr as_expr() const {
 | 
			
		||||
            unsigned n = size();
 | 
			
		||||
            if (n == 0) 
 | 
			
		||||
                return ctx().bool_val(false);
 | 
			
		||||
                return ctx().bool_val(true);
 | 
			
		||||
            else if (n == 1)
 | 
			
		||||
                return operator[](0);
 | 
			
		||||
            else {
 | 
			
		||||
| 
						 | 
				
			
			@ -1486,6 +1520,22 @@ namespace z3 {
 | 
			
		|||
        return function(range.ctx().str_symbol(name), arity, domain, range);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline func_decl context::function(symbol const& name, sort_vector const& domain, sort const& range) {
 | 
			
		||||
        array<Z3_sort> args(domain.size());
 | 
			
		||||
        for (unsigned i = 0; i < domain.size(); i++) {
 | 
			
		||||
            check_context(domain[i], range);
 | 
			
		||||
            args[i] = domain[i];
 | 
			
		||||
        }
 | 
			
		||||
        Z3_func_decl f = Z3_mk_func_decl(m_ctx, name, domain.size(), args.ptr(), range);
 | 
			
		||||
        check_error();
 | 
			
		||||
        return func_decl(*this, f);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    inline func_decl context::function(char const * name, sort_vector const& domain, sort const& range) {
 | 
			
		||||
        return function(range.ctx().str_symbol(name), domain, range);        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
    inline func_decl context::function(char const * name, sort const & domain, sort const & range) {
 | 
			
		||||
        check_context(domain, range);
 | 
			
		||||
        Z3_sort args[1] = { domain };
 | 
			
		||||
| 
						 | 
				
			
			@ -1571,6 +1621,16 @@ namespace z3 {
 | 
			
		|||
        return expr(ctx(), r);
 | 
			
		||||
    
 | 
			
		||||
    }
 | 
			
		||||
    inline expr func_decl::operator()(expr_vector const& args) const {
 | 
			
		||||
        array<Z3_ast> _args(args.size());
 | 
			
		||||
        for (unsigned i = 0; i < args.size(); i++) {
 | 
			
		||||
            check_context(*this, args[i]);
 | 
			
		||||
            _args[i] = args[i];
 | 
			
		||||
        }
 | 
			
		||||
        Z3_ast r = Z3_mk_app(ctx(), *this, args.size(), _args.ptr());
 | 
			
		||||
        check_error();
 | 
			
		||||
        return expr(ctx(), r);    
 | 
			
		||||
    }
 | 
			
		||||
    inline expr func_decl::operator()() const {
 | 
			
		||||
        Z3_ast r = Z3_mk_app(ctx(), *this, 0, 0);
 | 
			
		||||
        ctx().check_error();
 | 
			
		||||
| 
						 | 
				
			
			@ -1681,6 +1741,30 @@ namespace z3 {
 | 
			
		|||
        return expr(d.ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline expr expr::substitute(expr_vector const& src, expr_vector const& dst) {
 | 
			
		||||
        assert(src.size() == dst.size());
 | 
			
		||||
        array<Z3_ast> _src(src.size());
 | 
			
		||||
        array<Z3_ast> _dst(dst.size());    
 | 
			
		||||
        for (unsigned i = 0; i < src.size(); ++i) {
 | 
			
		||||
            _src[i] = src[i];
 | 
			
		||||
            _dst[i] = dst[i];
 | 
			
		||||
        }
 | 
			
		||||
        Z3_ast r = Z3_substitute(ctx(), m_ast, src.size(), _src.ptr(), _dst.ptr());
 | 
			
		||||
        check_error();
 | 
			
		||||
        return expr(ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    inline expr expr::substitute(expr_vector const& dst) {
 | 
			
		||||
        array<Z3_ast> _dst(dst.size());
 | 
			
		||||
        for (unsigned i = 0; i < dst.size(); ++i) {
 | 
			
		||||
            _dst[i] = dst[i];
 | 
			
		||||
        }
 | 
			
		||||
        Z3_ast r = Z3_substitute_vars(ctx(), m_ast, dst.size(), _dst.ptr());
 | 
			
		||||
        check_error();
 | 
			
		||||
        return expr(ctx(), r);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -44,6 +44,21 @@ namespace Microsoft.Z3
 | 
			
		|||
        /// <summary>
 | 
			
		||||
        /// Constructor.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        /// <remarks>
 | 
			
		||||
        /// The following parameters can be set:        
 | 
			
		||||
        ///     - proof  (Boolean)           Enable proof generation
 | 
			
		||||
        ///     - debug_ref_count (Boolean)  Enable debug support for Z3_ast reference counting 
 | 
			
		||||
        ///     - trace  (Boolean)           Tracing support for VCC
 | 
			
		||||
        ///     - trace_file_name (String)   Trace out file for VCC traces
 | 
			
		||||
        ///     - timeout (unsigned)         default timeout (in milliseconds) used for solvers
 | 
			
		||||
        ///     - well_sorted_check          type checker
 | 
			
		||||
        ///     - auto_config                use heuristics to automatically select solver and configure it
 | 
			
		||||
        ///     - model                      model generation for solvers, this parameter can be overwritten when creating a solver
 | 
			
		||||
        ///     - model_validate             validate models produced by solvers
 | 
			
		||||
        ///     - unsat_core                 unsat-core generation for solvers, this parameter can be overwritten when creating a solver
 | 
			
		||||
        /// Note that in previous versions of Z3, this constructor was also used to set global and module parameters. 
 | 
			
		||||
        /// For this purpose we should now use <see cref="Global.SetParameter"/>
 | 
			
		||||
        /// </remarks>
 | 
			
		||||
        public Context(Dictionary<string, string> settings)
 | 
			
		||||
            : base()
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -288,6 +303,9 @@ namespace Microsoft.Z3
 | 
			
		|||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new finite domain sort.
 | 
			
		||||
	/// <param name="name">The name used to identify the sort</param>
 | 
			
		||||
	/// <param size="size">The size of the sort</param>
 | 
			
		||||
	/// <returns>The result is a sort</returns>
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public FiniteDomainSort MkFiniteDomainSort(Symbol name, ulong size)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			@ -300,6 +318,11 @@ namespace Microsoft.Z3
 | 
			
		|||
 | 
			
		||||
        /// <summary>
 | 
			
		||||
        /// Create a new finite domain sort.
 | 
			
		||||
	/// <param name="name">The name used to identify the sort</param>
 | 
			
		||||
	/// <param size="size">The size of the sort</param>
 | 
			
		||||
	/// <returns>The result is a sort</returns>
 | 
			
		||||
	/// Elements of the sort are created using <seealso cref="MkNumeral"/>, 
 | 
			
		||||
	/// and the elements range from 0 to <tt>size-1</tt>.
 | 
			
		||||
        /// </summary>
 | 
			
		||||
        public FiniteDomainSort MkFiniteDomainSort(string name, ulong size)
 | 
			
		||||
        {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -210,7 +210,7 @@ namespace Microsoft.Z3
 | 
			
		|||
        public Status Check(params Expr[] assumptions)
 | 
			
		||||
        {
 | 
			
		||||
            Z3_lbool r;
 | 
			
		||||
            if (assumptions == null)
 | 
			
		||||
            if (assumptions == null || assumptions.Length == 0)
 | 
			
		||||
                r = (Z3_lbool)Native.Z3_solver_check(Context.nCtx, NativeObject);
 | 
			
		||||
            else
 | 
			
		||||
                r = (Z3_lbool)Native.Z3_solver_check_assumptions(Context.nCtx, NativeObject, (uint)assumptions.Length, AST.ArrayToNative(assumptions));
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -27,6 +27,21 @@ public class Context extends IDisposable
 | 
			
		|||
 | 
			
		||||
    /**
 | 
			
		||||
     * Constructor.
 | 
			
		||||
     * <remarks>
 | 
			
		||||
     * The following parameters can be set:        
 | 
			
		||||
     *     - proof  (Boolean)           Enable proof generation
 | 
			
		||||
     *     - debug_ref_count (Boolean)  Enable debug support for Z3_ast reference counting 
 | 
			
		||||
     *     - trace  (Boolean)           Tracing support for VCC
 | 
			
		||||
     *     - trace_file_name (String)   Trace out file for VCC traces
 | 
			
		||||
     *     - timeout (unsigned)         default timeout (in milliseconds) used for solvers
 | 
			
		||||
     *     - well_sorted_check          type checker
 | 
			
		||||
     *     - auto_config                use heuristics to automatically select solver and configure it
 | 
			
		||||
     *     - model                      model generation for solvers, this parameter can be overwritten when creating a solver
 | 
			
		||||
     *     - model_validate             validate models produced by solvers
 | 
			
		||||
     *     - unsat_core                 unsat-core generation for solvers, this parameter can be overwritten when creating a solver
 | 
			
		||||
     * Note that in previous versions of Z3, this constructor was also used to set global and 
 | 
			
		||||
     * module parameters. For this purpose we should now use <see cref="Global.setParameter"/>
 | 
			
		||||
     * </remarks>
 | 
			
		||||
     **/
 | 
			
		||||
    public Context(Map<String, String> settings) throws Z3Exception
 | 
			
		||||
    {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -12,7 +12,7 @@ package com.microsoft.z3;
 | 
			
		|||
public enum Status
 | 
			
		||||
{
 | 
			
		||||
    // / Used to signify an unsatisfiable status.
 | 
			
		||||
    UNSATISFIABLE(1),
 | 
			
		||||
    UNSATISFIABLE(-1),
 | 
			
		||||
 | 
			
		||||
    // / Used to signify an unknown status.
 | 
			
		||||
    UNKNOWN(0),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -585,6 +585,9 @@ class FuncDeclRef(AstRef):
 | 
			
		|||
    def as_ast(self):
 | 
			
		||||
        return Z3_func_decl_to_ast(self.ctx_ref(), self.ast)
 | 
			
		||||
 | 
			
		||||
    def as_func_decl(self):
 | 
			
		||||
	return self.ast
 | 
			
		||||
 | 
			
		||||
    def name(self):
 | 
			
		||||
        """Return the name of the function declaration `self`.
 | 
			
		||||
        
 | 
			
		||||
| 
						 | 
				
			
			@ -3853,32 +3856,6 @@ def is_array(a):
 | 
			
		|||
    """
 | 
			
		||||
    return isinstance(a, ArrayRef)
 | 
			
		||||
 | 
			
		||||
def is_select(a):
 | 
			
		||||
    """Return `True` if `a` is a Z3 array select.
 | 
			
		||||
    
 | 
			
		||||
    >>> a = Array('a', IntSort(), IntSort())
 | 
			
		||||
    >>> is_select(a)
 | 
			
		||||
    False
 | 
			
		||||
    >>> i = Int('i')
 | 
			
		||||
    >>> is_select(a[i])
 | 
			
		||||
    True
 | 
			
		||||
    """
 | 
			
		||||
    return is_app_of(a, Z3_OP_SELECT)
 | 
			
		||||
 | 
			
		||||
def is_store(a):
 | 
			
		||||
    """Return `True` if `a` is a Z3 array store.
 | 
			
		||||
    
 | 
			
		||||
    >>> a = Array('a', IntSort(), IntSort())
 | 
			
		||||
    >>> is_store(a)
 | 
			
		||||
    False
 | 
			
		||||
    >>> i = Int('i')
 | 
			
		||||
    >>> is_store(a[i])
 | 
			
		||||
    False
 | 
			
		||||
    >>> is_store(Store(a, i, i + 1))
 | 
			
		||||
    True
 | 
			
		||||
    """
 | 
			
		||||
    return is_app_of(a, Z3_OP_STORE)
 | 
			
		||||
 | 
			
		||||
def is_const_array(a):
 | 
			
		||||
    """Return `True` if `a` is a Z3 constant array.
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -4069,7 +4046,8 @@ def is_select(a):
 | 
			
		|||
    >>> a = Array('a', IntSort(), IntSort())
 | 
			
		||||
    >>> is_select(a)
 | 
			
		||||
    False
 | 
			
		||||
    >>> is_select(a[0])
 | 
			
		||||
    >>> i = Int('i')
 | 
			
		||||
    >>> is_select(a[i])
 | 
			
		||||
    True
 | 
			
		||||
    """
 | 
			
		||||
    return is_app_of(a, Z3_OP_SELECT)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -703,7 +703,7 @@ typedef enum
 | 
			
		|||
       over Boolean connectives 'and' and 'or'.
 | 
			
		||||
 | 
			
		||||
    
 | 
			
		||||
   - Z3_OP_PR_NFF_NEG: Proof for a (negative) NNF step. Examples:
 | 
			
		||||
   - Z3_OP_PR_NNF_NEG: Proof for a (negative) NNF step. Examples:
 | 
			
		||||
          \nicebox{
 | 
			
		||||
          T1: (not s_1) ~ r_1
 | 
			
		||||
          ...
 | 
			
		||||
| 
						 | 
				
			
			@ -780,11 +780,11 @@ typedef enum
 | 
			
		|||
        }
 | 
			
		||||
        or
 | 
			
		||||
        \nicebox{
 | 
			
		||||
             (=> (and ln+1 ln+2 .. ln+m) l0)
 | 
			
		||||
             (=> (and l1 l2 .. ln) l0)
 | 
			
		||||
        }
 | 
			
		||||
        or in the most general (ground) form:
 | 
			
		||||
        \nicebox{
 | 
			
		||||
             (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1))
 | 
			
		||||
             (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln))
 | 
			
		||||
        }
 | 
			
		||||
        In other words we use the following (Prolog style) convention for Horn 
 | 
			
		||||
        implications:
 | 
			
		||||
| 
						 | 
				
			
			@ -800,7 +800,7 @@ typedef enum
 | 
			
		|||
        general non-ground form is:
 | 
			
		||||
 | 
			
		||||
        \nicebox{
 | 
			
		||||
             (forall (vars) (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln-1)))
 | 
			
		||||
             (forall (vars) (=> (and ln+1 ln+2 .. ln+m) (or l0 l1 .. ln)))
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        The hyper-resolution rule takes a sequence of parameters.
 | 
			
		||||
| 
						 | 
				
			
			@ -1724,6 +1724,8 @@ extern "C" {
 | 
			
		|||
       To create constants that belong to the finite domain, 
 | 
			
		||||
       use the APIs for creating numerals and pass a numeric
 | 
			
		||||
       constant together with the sort returned by this call.
 | 
			
		||||
       The numeric constant should be between 0 and the less 
 | 
			
		||||
       than the size of the domain.
 | 
			
		||||
 | 
			
		||||
       \sa Z3_get_finite_domain_sort_size
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -26,6 +26,7 @@ Notes:
 | 
			
		|||
void register_z3_replayer_cmds(z3_replayer & in);
 | 
			
		||||
 | 
			
		||||
void throw_invalid_reference() {
 | 
			
		||||
    TRACE("z3_replayer", tout << "invalid argument reference\n";);
 | 
			
		||||
    throw z3_replayer_exception("invalid argument reference");
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -268,6 +268,8 @@ public:
 | 
			
		|||
    bool is_int_real(expr const * n) const { return is_int_real(get_sort(n)); }
 | 
			
		||||
 | 
			
		||||
    MATCH_UNARY(is_uminus);
 | 
			
		||||
    MATCH_UNARY(is_to_real);
 | 
			
		||||
    MATCH_UNARY(is_to_int);
 | 
			
		||||
    MATCH_BINARY(is_sub);
 | 
			
		||||
    MATCH_BINARY(is_add);
 | 
			
		||||
    MATCH_BINARY(is_mul);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -300,7 +300,7 @@ std::ostream & operator<<(std::ostream & out, func_decl_info const & info) {
 | 
			
		|||
//
 | 
			
		||||
// -----------------------------------
 | 
			
		||||
 | 
			
		||||
char const * g_ast_kind_names[] = {"application", "variable", "quantifier", "sort", "function declaration" };
 | 
			
		||||
static char const * g_ast_kind_names[] = {"application", "variable", "quantifier", "sort", "function declaration" };
 | 
			
		||||
 | 
			
		||||
char const * get_ast_kind_name(ast_kind k) {
 | 
			
		||||
    return g_ast_kind_names[k];
 | 
			
		||||
| 
						 | 
				
			
			@ -2765,7 +2765,7 @@ proof * ast_manager::mk_unit_resolution(unsigned num_proofs, proof * const * pro
 | 
			
		|||
        app const * cls   = to_app(f1);
 | 
			
		||||
        unsigned num_args = cls->get_num_args();
 | 
			
		||||
#ifdef Z3DEBUG
 | 
			
		||||
        vector<bool> found;
 | 
			
		||||
        svector<bool> found;
 | 
			
		||||
#endif
 | 
			
		||||
        for (unsigned i = 0; i < num_args; i++) {
 | 
			
		||||
            expr * lit = cls->get_arg(i);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1194,7 +1194,6 @@ enum pattern_op_kind {
 | 
			
		|||
   heurisitic quantifier instantiation.
 | 
			
		||||
*/
 | 
			
		||||
class pattern_decl_plugin : public decl_plugin {
 | 
			
		||||
    sort * m_list;
 | 
			
		||||
public:
 | 
			
		||||
    virtual decl_plugin * mk_fresh() { return alloc(pattern_decl_plugin); }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -134,6 +134,16 @@ bool lt(ast * n1, ast * n2) {
 | 
			
		|||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool is_sorted(unsigned num, expr * const * ns) {
 | 
			
		||||
    for (unsigned i = 1; i < num; i++) {
 | 
			
		||||
        ast * prev = ns[i-1];
 | 
			
		||||
        ast * curr = ns[i];
 | 
			
		||||
        if (lt(curr, prev))
 | 
			
		||||
            return false;
 | 
			
		||||
    }
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool lex_lt(unsigned num, ast * const * n1, ast * const * n2) {
 | 
			
		||||
    for (unsigned i = 0; i < num; i ++) {
 | 
			
		||||
        if (n1[i] == n2[i])
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,6 +22,7 @@ Revision History:
 | 
			
		|||
class ast;
 | 
			
		||||
 | 
			
		||||
bool lt(ast * n1, ast * n2);
 | 
			
		||||
bool is_sorted(unsigned num, expr * const * ns);
 | 
			
		||||
 | 
			
		||||
struct ast_to_lt {
 | 
			
		||||
    bool operator()(ast * n1, ast * n2) const { return lt(n1, n2); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -260,6 +260,7 @@ class smt_printer {
 | 
			
		|||
        else {
 | 
			
		||||
            m_out << sym << "[";
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        for (unsigned i = 0; i < num_params; ++i) {
 | 
			
		||||
            parameter const& p = params[i];
 | 
			
		||||
            if (p.is_ast()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -642,9 +643,7 @@ class smt_printer {
 | 
			
		|||
            m_out << m_var_names[m_num_var_names - idx - 1];
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            if (!m_is_smt2) {
 | 
			
		||||
                m_out << "?" << idx;
 | 
			
		||||
            }
 | 
			
		||||
            m_out << "?" << idx;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,3 +1,21 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2006 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    ast_util.cpp
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Helper functions
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Leonardo de Moura (leonardo) 2007-06-08.
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#include "ast_util.h"
 | 
			
		||||
 | 
			
		||||
app * mk_list_assoc_app(ast_manager & m, func_decl * f, unsigned num_args, expr * const * args) {
 | 
			
		||||
| 
						 | 
				
			
			@ -138,3 +156,38 @@ expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx) {
 | 
			
		|||
    SASSERT(m.is_or(cls));
 | 
			
		||||
    return to_app(cls)->get_arg(idx);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args) {
 | 
			
		||||
    if (num_args == 0)
 | 
			
		||||
        return m.mk_true();
 | 
			
		||||
    else if (num_args == 1)
 | 
			
		||||
        return args[0];
 | 
			
		||||
    else
 | 
			
		||||
        return m.mk_and(num_args, args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args) {
 | 
			
		||||
    if (num_args == 0)
 | 
			
		||||
        return m.mk_false();
 | 
			
		||||
    else if (num_args == 1)
 | 
			
		||||
        return args[0];
 | 
			
		||||
    else
 | 
			
		||||
        return m.mk_or(num_args, args);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr * mk_not(ast_manager & m, expr * arg) {
 | 
			
		||||
    expr * atom;
 | 
			
		||||
    if (m.is_not(arg, atom))
 | 
			
		||||
        return atom;
 | 
			
		||||
    else
 | 
			
		||||
        return m.mk_not(arg);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args) {
 | 
			
		||||
    expr_ref_buffer new_diseqs(m);
 | 
			
		||||
    for (unsigned i = 0; i < num_args; i++) {
 | 
			
		||||
        for (unsigned j = i + 1; j < num_args; j++)
 | 
			
		||||
            new_diseqs.push_back(m.mk_not(m.mk_eq(args[i], args[j])));
 | 
			
		||||
    }
 | 
			
		||||
    return mk_and(m, new_diseqs.size(), new_diseqs.c_ptr());
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -95,5 +95,36 @@ bool is_clause(ast_manager & m, expr * n);
 | 
			
		|||
unsigned get_clause_num_literals(ast_manager & m, expr * cls);
 | 
			
		||||
expr * get_clause_literal(ast_manager & m, expr * cls, unsigned idx);
 | 
			
		||||
 | 
			
		||||
// -----------------------------------
 | 
			
		||||
//
 | 
			
		||||
// Goodies for creating Boolean expressions
 | 
			
		||||
//
 | 
			
		||||
// -----------------------------------
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   Return (and args[0] ... args[num_args-1]) if num_args >= 2
 | 
			
		||||
   Return args[0]                            if num_args == 1
 | 
			
		||||
   Return true                               if num_args == 0
 | 
			
		||||
 */
 | 
			
		||||
expr * mk_and(ast_manager & m, unsigned num_args, expr * const * args);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   Return (or args[0] ... args[num_args-1]) if num_args >= 2
 | 
			
		||||
   Return args[0]                           if num_args == 1
 | 
			
		||||
   Return false                             if num_args == 0
 | 
			
		||||
 */
 | 
			
		||||
expr * mk_or(ast_manager & m, unsigned num_args, expr * const * args);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   Return a          if arg = (not a)
 | 
			
		||||
   Retur (not arg)   otherwise
 | 
			
		||||
 */
 | 
			
		||||
expr * mk_not(ast_manager & m, expr * arg);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   Return the expression (and (not (= args[0] args[1])) (not (= args[0] args[2])) ... (not (= args[num_args-2] args[num_args-1])))
 | 
			
		||||
*/
 | 
			
		||||
expr * expand_distinct(ast_manager & m, unsigned num_args, expr * const * args);
 | 
			
		||||
 | 
			
		||||
#endif /* _AST_UTIL_H_ */
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -210,6 +210,10 @@ func_decl * bv_decl_plugin::mk_unary(ptr_vector<func_decl> & decls, decl_kind k,
 | 
			
		|||
 | 
			
		||||
func_decl * bv_decl_plugin::mk_int2bv(unsigned bv_size, unsigned num_parameters, parameter const * parameters,
 | 
			
		||||
                                    unsigned arity, sort * const * domain) {
 | 
			
		||||
    if (bv_size == 0) {
 | 
			
		||||
        m_manager->raise_exception("bit-vector size must be greater than zero");
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    force_ptr_array_size(m_int2bv, bv_size + 1);
 | 
			
		||||
 | 
			
		||||
    if (arity != 1) {
 | 
			
		||||
| 
						 | 
				
			
			@ -415,6 +419,9 @@ func_decl * bv_decl_plugin::mk_num_decl(unsigned num_parameters, parameter const
 | 
			
		|||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
    unsigned bv_size = parameters[1].get_int();
 | 
			
		||||
    if (bv_size == 0) {
 | 
			
		||||
        m_manager->raise_exception("bit-vector size must be greater than zero");
 | 
			
		||||
    }
 | 
			
		||||
    // TODO: sign an error if the parameters[0] is out of range, that is, it is a value not in [0, 2^{bv_size})
 | 
			
		||||
    // This cannot be enforced now, since some Z3 modules try to generate these invalid numerals.
 | 
			
		||||
    // After SMT-COMP, I should find all offending modules.
 | 
			
		||||
| 
						 | 
				
			
			@ -766,7 +773,7 @@ bool bv_recognizers::is_zero(expr const * n) const {
 | 
			
		|||
    return decl->get_parameter(0).get_rational().is_zero();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) {
 | 
			
		||||
bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, expr*& b) const {
 | 
			
		||||
    if (!is_extract(e)) return false;
 | 
			
		||||
    low = get_extract_low(e);
 | 
			
		||||
    high = get_extract_high(e);
 | 
			
		||||
| 
						 | 
				
			
			@ -774,7 +781,7 @@ bool bv_recognizers::is_extract(expr const* e, unsigned& low, unsigned& high, ex
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) {
 | 
			
		||||
bool bv_recognizers::is_bv2int(expr const* e, expr*& r) const {
 | 
			
		||||
    if (!is_bv2int(e)) return false;
 | 
			
		||||
    r = to_app(e)->get_arg(0);
 | 
			
		||||
    return true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -288,10 +288,10 @@ public:
 | 
			
		|||
    bool is_extract(expr const * e) const { return is_app_of(e, get_fid(), OP_EXTRACT); }
 | 
			
		||||
    unsigned get_extract_high(func_decl const * f) const { return f->get_parameter(0).get_int(); }
 | 
			
		||||
    unsigned get_extract_low(func_decl const * f) const { return f->get_parameter(1).get_int(); }
 | 
			
		||||
    unsigned get_extract_high(expr const * n) { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); }
 | 
			
		||||
    unsigned get_extract_low(expr const * n) { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); }
 | 
			
		||||
    bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b);
 | 
			
		||||
    bool is_bv2int(expr const * e, expr * & r);
 | 
			
		||||
    unsigned get_extract_high(expr const * n) const { SASSERT(is_extract(n)); return get_extract_high(to_app(n)->get_decl()); }
 | 
			
		||||
    unsigned get_extract_low(expr const * n) const { SASSERT(is_extract(n)); return get_extract_low(to_app(n)->get_decl()); }
 | 
			
		||||
    bool is_extract(expr const * e, unsigned & low, unsigned & high, expr * & b) const;
 | 
			
		||||
    bool is_bv2int(expr const * e, expr * & r) const;
 | 
			
		||||
    bool is_bv_add(expr const * e) const { return is_app_of(e, get_fid(), OP_BADD); }
 | 
			
		||||
    bool is_bv_sub(expr const * e) const { return is_app_of(e, get_fid(), OP_BSUB); }
 | 
			
		||||
    bool is_bv_mul(expr const * e) const { return is_app_of(e, get_fid(), OP_BMUL); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -84,7 +84,8 @@ class datatype_decl {
 | 
			
		|||
    ptr_vector<constructor_decl> m_constructors;
 | 
			
		||||
public:
 | 
			
		||||
    datatype_decl(const symbol & n, unsigned num_constructors, constructor_decl * const * constructors):
 | 
			
		||||
        m_name(n), m_constructors(num_constructors, constructors) {}
 | 
			
		||||
        m_name(n), m_constructors(num_constructors, constructors) {
 | 
			
		||||
    }
 | 
			
		||||
    ~datatype_decl() {
 | 
			
		||||
        std::for_each(m_constructors.begin(), m_constructors.end(), delete_proc<constructor_decl>());
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -326,6 +326,7 @@ namespace datalog {
 | 
			
		|||
        }
 | 
			
		||||
        unsigned index0;
 | 
			
		||||
        sort* last_sort = 0;
 | 
			
		||||
        SASSERT(num_params > 0);
 | 
			
		||||
        for (unsigned i = 0; i < num_params; ++i) {
 | 
			
		||||
            parameter const& p = params[i];
 | 
			
		||||
            if (!p.is_int()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -636,6 +637,10 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
    app* dl_decl_util::mk_numeral(uint64 value, sort* s) {
 | 
			
		||||
        if (is_finite_sort(s)) {
 | 
			
		||||
            uint64 sz = 0;
 | 
			
		||||
            if (try_get_size(s, sz) && sz <= value) {
 | 
			
		||||
                m.raise_exception("value is out of bounds");
 | 
			
		||||
            }
 | 
			
		||||
            parameter params[2] = { parameter(rational(value, rational::ui64())), parameter(s) };
 | 
			
		||||
            return m.mk_const(m.mk_func_decl(m_fid, OP_DL_CONSTANT, 2, params, 0, (sort*const*)0));
 | 
			
		||||
        }        
 | 
			
		||||
| 
						 | 
				
			
			@ -652,13 +657,15 @@ namespace datalog {
 | 
			
		|||
            SASSERT(value == 1);
 | 
			
		||||
            return m.mk_true();
 | 
			
		||||
        }
 | 
			
		||||
        m.raise_exception("unrecognized sort");
 | 
			
		||||
        std::stringstream strm;
 | 
			
		||||
        strm << "sort '" << mk_pp(s, m) << "' is not recognized as a sort that contains numeric values.\nUse Bool, BitVec, Int, Real, or a Finite domain sort";
 | 
			
		||||
        m.raise_exception(strm.str().c_str());
 | 
			
		||||
        return 0;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool dl_decl_util::is_numeral(expr* e, uint64& v) const {
 | 
			
		||||
    bool dl_decl_util::is_numeral(const expr* e, uint64& v) const {
 | 
			
		||||
        if (is_numeral(e)) {
 | 
			
		||||
            app* c = to_app(e);
 | 
			
		||||
            const app* c = to_app(e);
 | 
			
		||||
            SASSERT(c->get_decl()->get_num_parameters() == 2);
 | 
			
		||||
            parameter const& p = c->get_decl()->get_parameter(0);
 | 
			
		||||
            SASSERT(p.is_rational());
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,11 +169,11 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
        app* mk_le(expr* a, expr* b);
 | 
			
		||||
 | 
			
		||||
        bool is_lt(expr* a) { return is_app_of(a, m_fid, OP_DL_LT); }
 | 
			
		||||
        bool is_lt(const expr* a) const { return is_app_of(a, m_fid, OP_DL_LT); }
 | 
			
		||||
 | 
			
		||||
        bool is_numeral(expr* c) const { return is_app_of(c, m_fid, OP_DL_CONSTANT); }
 | 
			
		||||
        bool is_numeral(const expr* c) const { return is_app_of(c, m_fid, OP_DL_CONSTANT); }
 | 
			
		||||
 | 
			
		||||
        bool is_numeral(expr* e, uint64& v) const;
 | 
			
		||||
        bool is_numeral(const expr* e, uint64& v) const;
 | 
			
		||||
 | 
			
		||||
        //
 | 
			
		||||
        // Utilities for extracting constants 
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,52 +20,50 @@ Notes:
 | 
			
		|||
#include "expr_abstract.h"
 | 
			
		||||
#include "map.h"
 | 
			
		||||
 | 
			
		||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref&  result) {
 | 
			
		||||
    ast_ref_vector pinned(m);
 | 
			
		||||
    ptr_vector<expr> stack;
 | 
			
		||||
    obj_map<expr, expr*> map;
 | 
			
		||||
void expr_abstractor::operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result) {
 | 
			
		||||
    
 | 
			
		||||
    expr * curr = 0, *b = 0;
 | 
			
		||||
    SASSERT(n->get_ref_count() > 0);
 | 
			
		||||
 | 
			
		||||
    stack.push_back(n);
 | 
			
		||||
    m_stack.push_back(n);
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < num_bound; ++i) {
 | 
			
		||||
        b = bound[i];
 | 
			
		||||
        expr* v = m.mk_var(base + num_bound - i - 1, m.get_sort(b));
 | 
			
		||||
        pinned.push_back(v);
 | 
			
		||||
        map.insert(b, v);
 | 
			
		||||
        m_pinned.push_back(v);
 | 
			
		||||
        m_map.insert(b, v);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    while(!stack.empty()) {
 | 
			
		||||
        curr = stack.back();
 | 
			
		||||
        if (map.contains(curr)) {
 | 
			
		||||
            stack.pop_back();
 | 
			
		||||
    while(!m_stack.empty()) {
 | 
			
		||||
        curr = m_stack.back();
 | 
			
		||||
        if (m_map.contains(curr)) {
 | 
			
		||||
            m_stack.pop_back();
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        switch(curr->get_kind()) {
 | 
			
		||||
        case AST_VAR: {
 | 
			
		||||
            map.insert(curr, curr);
 | 
			
		||||
            stack.pop_back();
 | 
			
		||||
            m_map.insert(curr, curr);
 | 
			
		||||
            m_stack.pop_back();
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case AST_APP: {
 | 
			
		||||
            app* a = to_app(curr);
 | 
			
		||||
            bool all_visited = true;
 | 
			
		||||
            ptr_vector<expr> args;
 | 
			
		||||
            m_args.reset();
 | 
			
		||||
            for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
			
		||||
                if (!map.find(a->get_arg(i), b)) {
 | 
			
		||||
                    stack.push_back(a->get_arg(i));
 | 
			
		||||
                if (!m_map.find(a->get_arg(i), b)) {
 | 
			
		||||
                    m_stack.push_back(a->get_arg(i));
 | 
			
		||||
                    all_visited = false;
 | 
			
		||||
                }
 | 
			
		||||
                else {
 | 
			
		||||
                    args.push_back(b);
 | 
			
		||||
                    m_args.push_back(b);
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            if (all_visited) {
 | 
			
		||||
                b = m.mk_app(a->get_decl(), args.size(), args.c_ptr());
 | 
			
		||||
                pinned.push_back(b);
 | 
			
		||||
                map.insert(curr, b);
 | 
			
		||||
                stack.pop_back();
 | 
			
		||||
                b = m.mk_app(a->get_decl(), m_args.size(), m_args.c_ptr());
 | 
			
		||||
                m_pinned.push_back(b);
 | 
			
		||||
                m_map.insert(curr, b);
 | 
			
		||||
                m_stack.pop_back();
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -81,17 +79,24 @@ void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* cons
 | 
			
		|||
            }
 | 
			
		||||
            expr_abstract(m, new_base, num_bound, bound, q->get_expr(), result1);
 | 
			
		||||
            b = m.update_quantifier(q, patterns.size(), patterns.c_ptr(), result1.get());
 | 
			
		||||
            pinned.push_back(b);            
 | 
			
		||||
            map.insert(curr, b);
 | 
			
		||||
            stack.pop_back();            
 | 
			
		||||
            m_pinned.push_back(b);            
 | 
			
		||||
            m_map.insert(curr, b);
 | 
			
		||||
            m_stack.pop_back();            
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default:
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    if (!map.find(n, b)) {
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
    }
 | 
			
		||||
    VERIFY (m_map.find(n, b));
 | 
			
		||||
    result = b;
 | 
			
		||||
    m_pinned.reset();
 | 
			
		||||
    m_map.reset();
 | 
			
		||||
    m_stack.reset();
 | 
			
		||||
    m_args.reset();   
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref&  result) {
 | 
			
		||||
    expr_abstractor abs(m);
 | 
			
		||||
    abs(base, num_bound, bound, n, result);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -21,6 +21,17 @@ Notes:
 | 
			
		|||
 | 
			
		||||
#include"ast.h"
 | 
			
		||||
 | 
			
		||||
class expr_abstractor {
 | 
			
		||||
    ast_manager& m;
 | 
			
		||||
    expr_ref_vector m_pinned;
 | 
			
		||||
    ptr_vector<expr> m_stack, m_args;
 | 
			
		||||
    obj_map<expr, expr*> m_map;
 | 
			
		||||
    
 | 
			
		||||
public:
 | 
			
		||||
    expr_abstractor(ast_manager& m): m(m), m_pinned(m) {}
 | 
			
		||||
    void operator()(unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref& result);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void expr_abstract(ast_manager& m, unsigned base, unsigned num_bound, expr* const* bound, expr* n, expr_ref&  result);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -200,6 +200,7 @@ func_decl * float_decl_plugin::mk_float_const_decl(decl_kind k, unsigned num_par
 | 
			
		|||
    }
 | 
			
		||||
    else {
 | 
			
		||||
        m_manager->raise_exception("sort of floating point constant was not specified");
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    SASSERT(is_sort_of(s, m_family_id, FLOAT_SORT));
 | 
			
		||||
| 
						 | 
				
			
			@ -255,6 +256,10 @@ func_decl * float_decl_plugin::mk_unary_rel_decl(decl_kind k, unsigned num_param
 | 
			
		|||
    case OP_FLOAT_IS_NZERO: name = "isNZero";   break;
 | 
			
		||||
    case OP_FLOAT_IS_PZERO: name = "isPZero";   break;        
 | 
			
		||||
    case OP_FLOAT_IS_SIGN_MINUS: name = "isSignMinus";  break;
 | 
			
		||||
    case OP_FLOAT_IS_NAN: name = "isNaN";  break;
 | 
			
		||||
    case OP_FLOAT_IS_INF: name = "isInfinite";  break;
 | 
			
		||||
    case OP_FLOAT_IS_NORMAL: name = "isNormal";  break;
 | 
			
		||||
    case OP_FLOAT_IS_SUBNORMAL: name = "isSubnormal";  break;
 | 
			
		||||
    default:
 | 
			
		||||
        UNREACHABLE();
 | 
			
		||||
        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -353,27 +358,22 @@ func_decl * float_decl_plugin::mk_to_float(decl_kind k, unsigned num_parameters,
 | 
			
		|||
        sort * fp = mk_float_sort(domain[2]->get_parameter(0).get_int(), domain[1]->get_parameter(0).get_int()+1);
 | 
			
		||||
        symbol name("asFloat");
 | 
			
		||||
        return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
 | 
			
		||||
        }
 | 
			
		||||
    }    
 | 
			
		||||
    else {
 | 
			
		||||
        // .. Otherwise we only know how to convert rationals/reals. 
 | 
			
		||||
        if (!(num_parameters == 2 && parameters[0].is_int() && parameters[1].is_int())) 
 | 
			
		||||
            m_manager->raise_exception("expecting two integer parameters to asFloat");        
 | 
			
		||||
        if (arity != 2 && arity != 3)
 | 
			
		||||
            m_manager->raise_exception("invalid number of arguments to asFloat operator");
 | 
			
		||||
        if (!is_rm_sort(domain[0]) || domain[1] != m_real_sort)
 | 
			
		||||
        if (arity == 3 && domain[2] != m_int_sort)
 | 
			
		||||
            m_manager->raise_exception("sort mismatch");     
 | 
			
		||||
        if (arity == 2) {            
 | 
			
		||||
            sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
 | 
			
		||||
            symbol name("asFloat");
 | 
			
		||||
            return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            if (domain[2] != m_int_sort)
 | 
			
		||||
                m_manager->raise_exception("sort mismatch");     
 | 
			
		||||
            sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
 | 
			
		||||
            symbol name("asFloat");
 | 
			
		||||
            return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));
 | 
			
		||||
        }
 | 
			
		||||
        if (!is_rm_sort(domain[0]) ||
 | 
			
		||||
            !(domain[1] == m_real_sort || is_sort_of(domain[1], m_family_id, FLOAT_SORT)))
 | 
			
		||||
            m_manager->raise_exception("sort mismatch");
 | 
			
		||||
        
 | 
			
		||||
        sort * fp = mk_float_sort(parameters[0].get_int(), parameters[1].get_int());
 | 
			
		||||
        symbol name("asFloat");
 | 
			
		||||
        return m_manager->mk_func_decl(name, arity, domain, fp, func_decl_info(m_family_id, k, num_parameters, parameters));            
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -419,6 +419,10 @@ func_decl * float_decl_plugin::mk_func_decl(decl_kind k, unsigned num_parameters
 | 
			
		|||
    case OP_FLOAT_IS_NZERO:
 | 
			
		||||
    case OP_FLOAT_IS_PZERO:
 | 
			
		||||
    case OP_FLOAT_IS_SIGN_MINUS: 
 | 
			
		||||
    case OP_FLOAT_IS_NAN:
 | 
			
		||||
    case OP_FLOAT_IS_INF:
 | 
			
		||||
    case OP_FLOAT_IS_NORMAL:
 | 
			
		||||
    case OP_FLOAT_IS_SUBNORMAL:
 | 
			
		||||
        return mk_unary_rel_decl(k, num_parameters, parameters, arity, domain, range);
 | 
			
		||||
    case OP_FLOAT_ABS: 
 | 
			
		||||
    case OP_FLOAT_UMINUS:
 | 
			
		||||
| 
						 | 
				
			
			@ -477,9 +481,13 @@ void float_decl_plugin::get_op_names(svector<builtin_name> & op_names, symbol co
 | 
			
		|||
    op_names.push_back(builtin_name("<=", OP_FLOAT_LE));
 | 
			
		||||
    op_names.push_back(builtin_name(">=", OP_FLOAT_GE));
 | 
			
		||||
 | 
			
		||||
    op_names.push_back(builtin_name("isNaN", OP_FLOAT_IS_NAN));
 | 
			
		||||
    op_names.push_back(builtin_name("isInfinite", OP_FLOAT_IS_INF));
 | 
			
		||||
    op_names.push_back(builtin_name("isZero", OP_FLOAT_IS_ZERO));
 | 
			
		||||
    op_names.push_back(builtin_name("isNZero", OP_FLOAT_IS_NZERO));
 | 
			
		||||
    op_names.push_back(builtin_name("isPZero", OP_FLOAT_IS_PZERO));
 | 
			
		||||
    op_names.push_back(builtin_name("isNormal", OP_FLOAT_IS_NORMAL));
 | 
			
		||||
    op_names.push_back(builtin_name("isSubnormal", OP_FLOAT_IS_SUBNORMAL));
 | 
			
		||||
    op_names.push_back(builtin_name("isSignMinus", OP_FLOAT_IS_SIGN_MINUS));
 | 
			
		||||
 | 
			
		||||
    op_names.push_back(builtin_name("min", OP_FLOAT_MIN));
 | 
			
		||||
| 
						 | 
				
			
			@ -496,6 +504,15 @@ void float_decl_plugin::get_sort_names(svector<builtin_name> & sort_names, symbo
 | 
			
		|||
    sort_names.push_back(builtin_name("RoundingMode", ROUNDING_MODE_SORT));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
expr * float_decl_plugin::get_some_value(sort * s) {
 | 
			
		||||
    SASSERT(s->is_sort_of(m_family_id, FLOAT_SORT));    
 | 
			
		||||
    mpf tmp;
 | 
			
		||||
    m_fm.mk_nan(s->get_parameter(0).get_int(), s->get_parameter(1).get_int(), tmp);
 | 
			
		||||
    expr * res = this->mk_value(tmp);
 | 
			
		||||
    m_fm.del(tmp);
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool float_decl_plugin::is_value(app * e) const {
 | 
			
		||||
    if (e->get_family_id() != m_family_id) 
 | 
			
		||||
        return false;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -61,9 +61,13 @@ enum float_op_kind {
 | 
			
		|||
    OP_FLOAT_GT,
 | 
			
		||||
    OP_FLOAT_LE,
 | 
			
		||||
    OP_FLOAT_GE,
 | 
			
		||||
    OP_FLOAT_IS_NAN,
 | 
			
		||||
    OP_FLOAT_IS_INF,
 | 
			
		||||
    OP_FLOAT_IS_ZERO,
 | 
			
		||||
    OP_FLOAT_IS_NZERO,
 | 
			
		||||
    OP_FLOAT_IS_NORMAL,
 | 
			
		||||
    OP_FLOAT_IS_SUBNORMAL,    
 | 
			
		||||
    OP_FLOAT_IS_PZERO,
 | 
			
		||||
    OP_FLOAT_IS_NZERO,
 | 
			
		||||
    OP_FLOAT_IS_SIGN_MINUS,
 | 
			
		||||
 | 
			
		||||
    OP_TO_FLOAT,
 | 
			
		||||
| 
						 | 
				
			
			@ -140,6 +144,7 @@ public:
 | 
			
		|||
                                     unsigned arity, sort * const * domain, sort * range);
 | 
			
		||||
    virtual void get_op_names(svector<builtin_name> & op_names, symbol const & logic);
 | 
			
		||||
    virtual void get_sort_names(svector<builtin_name> & sort_names, symbol const & logic);
 | 
			
		||||
    virtual expr * get_some_value(sort * s);
 | 
			
		||||
    virtual bool is_value(app* e) const;
 | 
			
		||||
    virtual bool is_unique_value(app* e) const { return is_value(e); }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -222,7 +227,7 @@ public:
 | 
			
		|||
    app * mk_rem(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_REM, arg1, arg2); }
 | 
			
		||||
    app * mk_max(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MAX, arg1, arg2); }
 | 
			
		||||
    app * mk_min(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_MIN, arg1, arg2); }
 | 
			
		||||
    app * mk_abs(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1, arg2); }
 | 
			
		||||
    app * mk_abs(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_ABS, arg1); }
 | 
			
		||||
    app * mk_sqrt(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_SQRT, arg1, arg2); }
 | 
			
		||||
    app * mk_round(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_ROUND_TO_INTEGRAL, arg1, arg2); }
 | 
			
		||||
    app * mk_fused_ma(expr * arg1, expr * arg2, expr * arg3, expr * arg4) {
 | 
			
		||||
| 
						 | 
				
			
			@ -236,7 +241,11 @@ public:
 | 
			
		|||
    app * mk_le(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_LE, arg1, arg2); }
 | 
			
		||||
    app * mk_ge(expr * arg1, expr * arg2) { return m().mk_app(m_fid, OP_FLOAT_GE, arg1, arg2); }
 | 
			
		||||
 | 
			
		||||
    app * mk_is_nan(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NAN, arg1); }
 | 
			
		||||
    app * mk_is_inf(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_INF, arg1); }
 | 
			
		||||
    app * mk_is_zero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_ZERO, arg1); }
 | 
			
		||||
    app * mk_is_normal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NORMAL, arg1); }
 | 
			
		||||
    app * mk_is_subnormal(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SUBNORMAL, arg1); }
 | 
			
		||||
    app * mk_is_nzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_NZERO, arg1); }
 | 
			
		||||
    app * mk_is_pzero(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_PZERO, arg1); }
 | 
			
		||||
    app * mk_is_sign_minus(expr * arg1) { return m().mk_app(m_fid, OP_FLOAT_IS_SIGN_MINUS, arg1); }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -79,7 +79,6 @@ void func_decl_dependencies::collect_ng_func_decls(expr * n, func_decl_set * s)
 | 
			
		|||
*/
 | 
			
		||||
class func_decl_dependencies::top_sort {
 | 
			
		||||
    enum color { OPEN, IN_PROGRESS, CLOSED };
 | 
			
		||||
    ast_manager &       m_manager;    
 | 
			
		||||
    dependency_graph &  m_deps;
 | 
			
		||||
 | 
			
		||||
    typedef obj_map<func_decl, color> color_map;
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +176,7 @@ class func_decl_dependencies::top_sort {
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    top_sort(ast_manager & m, dependency_graph & deps):m_manager(m), m_deps(deps) {}
 | 
			
		||||
    top_sort(dependency_graph & deps) : m_deps(deps) {}
 | 
			
		||||
    
 | 
			
		||||
    bool operator()(func_decl * new_decl) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +197,7 @@ bool func_decl_dependencies::insert(func_decl * f, func_decl_set * s) {
 | 
			
		|||
 | 
			
		||||
    m_deps.insert(f, s);
 | 
			
		||||
 | 
			
		||||
    top_sort cycle_detector(m_manager, m_deps);
 | 
			
		||||
    top_sort cycle_detector(m_deps);
 | 
			
		||||
    if (cycle_detector(f)) {
 | 
			
		||||
        m_deps.erase(f);
 | 
			
		||||
        dealloc(s);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -597,8 +597,9 @@ void hint_to_macro_head(ast_manager & m, app * head, unsigned num_decls, app_ref
 | 
			
		|||
   is_hint_head(head, vars) must also return true
 | 
			
		||||
*/
 | 
			
		||||
bool macro_util::is_poly_hint(expr * n, app * head, expr * exception) {
 | 
			
		||||
    TRACE("macro_util_hint", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n"
 | 
			
		||||
          << mk_pp(exception, m_manager) << "\n";);
 | 
			
		||||
    TRACE("macro_util_hint", tout << "is_poly_hint n:\n" << mk_pp(n, m_manager) << "\nhead:\n" << mk_pp(head, m_manager) << "\nexception:\n";
 | 
			
		||||
          if (exception) tout << mk_pp(exception, m_manager); else tout << "<null>";
 | 
			
		||||
          tout << "\n";);
 | 
			
		||||
    ptr_buffer<var> vars;
 | 
			
		||||
    if (!is_hint_head(head, vars)) {
 | 
			
		||||
        TRACE("macro_util_hint", tout << "failed because head is not hint head\n";);
 | 
			
		||||
| 
						 | 
				
			
			@ -792,7 +793,10 @@ void macro_util::collect_arith_macro_candidates(expr * lhs, expr * rhs, expr * a
 | 
			
		|||
            mk_add(args.size(), args.c_ptr(), m_manager.get_sort(arg), rest);
 | 
			
		||||
            expr_ref def(m_manager);
 | 
			
		||||
            mk_sub(rhs, rest, def);
 | 
			
		||||
            add_arith_macro_candidate(to_app(arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
 | 
			
		||||
            // If is_poly_hint, rhs may contain variables that do not occur in to_app(arg).
 | 
			
		||||
            // So, we should re-check.
 | 
			
		||||
            if (!_is_poly_hint || is_poly_hint(def, to_app(arg), 0))
 | 
			
		||||
                add_arith_macro_candidate(to_app(arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
 | 
			
		||||
        }
 | 
			
		||||
        else if (is_times_minus_one(arg, neg_arg) && is_app(neg_arg)) {
 | 
			
		||||
            f = to_app(neg_arg)->get_decl();
 | 
			
		||||
| 
						 | 
				
			
			@ -810,7 +814,10 @@ void macro_util::collect_arith_macro_candidates(expr * lhs, expr * rhs, expr * a
 | 
			
		|||
                mk_add(args.size(), args.c_ptr(), m_manager.get_sort(arg), rest);
 | 
			
		||||
                expr_ref def(m_manager);
 | 
			
		||||
                mk_sub(rest, rhs, def);
 | 
			
		||||
                add_arith_macro_candidate(to_app(neg_arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
 | 
			
		||||
                // If is_poly_hint, rhs may contain variables that do not occur in to_app(neg_arg).
 | 
			
		||||
                // So, we should re-check.
 | 
			
		||||
                if (!_is_poly_hint || is_poly_hint(def, to_app(neg_arg), 0))
 | 
			
		||||
                    add_arith_macro_candidate(to_app(neg_arg), num_decls, def, atom, is_ineq, _is_poly_hint, r);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -22,10 +22,9 @@ Revision History:
 | 
			
		|||
#include"uint_set.h"
 | 
			
		||||
#include"var_subst.h"
 | 
			
		||||
 | 
			
		||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, basic_simplifier_plugin & p, simplifier & s) :
 | 
			
		||||
quasi_macros::quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s) :
 | 
			
		||||
  m_manager(m),
 | 
			
		||||
  m_macro_manager(mm),
 | 
			
		||||
  m_bsimp(p), 
 | 
			
		||||
  m_simplifier(s),
 | 
			
		||||
  m_new_vars(m),
 | 
			
		||||
  m_new_eqs(m),
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -32,7 +32,6 @@ class quasi_macros {
 | 
			
		|||
 | 
			
		||||
    ast_manager &             m_manager;
 | 
			
		||||
    macro_manager &           m_macro_manager;
 | 
			
		||||
    basic_simplifier_plugin & m_bsimp;   
 | 
			
		||||
    simplifier &              m_simplifier;
 | 
			
		||||
    occurrences_map           m_occurrences;
 | 
			
		||||
    ptr_vector<expr>          m_todo;    
 | 
			
		||||
| 
						 | 
				
			
			@ -57,7 +56,7 @@ class quasi_macros {
 | 
			
		|||
    void apply_macros(unsigned n, expr * const * exprs, proof * const * prs, expr_ref_vector & new_exprs, proof_ref_vector & new_prs);
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    quasi_macros(ast_manager & m, macro_manager & mm, basic_simplifier_plugin & p, simplifier & s);
 | 
			
		||||
    quasi_macros(ast_manager & m, macro_manager & mm, simplifier & s);
 | 
			
		||||
    ~quasi_macros();
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -119,13 +119,13 @@
 | 
			
		|||
                 :pattern (?select (?select (?asElems e) a) i))))
 | 
			
		||||
(assert (forall ((x Int) (f Int) (a0 Int))
 | 
			
		||||
                (!
 | 
			
		||||
                 (or (<= (+ a0 (* -1 (?fClosedTime f))) 0)
 | 
			
		||||
                 (or (<= (+ a0 (* (- 1) (?fClosedTime f))) 0)
 | 
			
		||||
                     (not (= (?isAllocated x a0) 1))
 | 
			
		||||
                     (= (?isAllocated (?select f x) a0) 1))
 | 
			
		||||
                 :pattern (?isAllocated (?select f x) a0))))
 | 
			
		||||
(assert (forall ((a Int) (e Int) (i Int) (a0 Int))
 | 
			
		||||
                (!
 | 
			
		||||
                 (or (<= (+ a0 (* -1 (?eClosedTime e))) 0)
 | 
			
		||||
                 (or (<= (+ a0 (* (- 1) (?eClosedTime e))) 0)
 | 
			
		||||
                     (not (= (?isAllocated a a0) 1))
 | 
			
		||||
                     (= (?isAllocated (?select (?select e a) i) a0) 1))
 | 
			
		||||
                 :pattern (?isAllocated (?select (?select e a) i) a0))))
 | 
			
		||||
| 
						 | 
				
			
			@ -281,13 +281,13 @@
 | 
			
		|||
                  :pattern (IntsAllocated h (?StructGet_ s f)))))
 | 
			
		||||
(assert  (forall ((x Int) (f Int) (a0 Int))
 | 
			
		||||
                 (!
 | 
			
		||||
                  (or (<= (+ a0 (* -1 (?fClosedTime f))) 0)
 | 
			
		||||
                  (or (<= (+ a0 (* (- 1) (?fClosedTime f))) 0)
 | 
			
		||||
                      (not (?isAllocated_ x a0))
 | 
			
		||||
                      (?isAllocated_ (?select f x) a0))
 | 
			
		||||
                  :pattern (?isAllocated_ (?select f x) a0))))
 | 
			
		||||
(assert  (forall ((a Int) (e Int) (i Int) (a0 Int))
 | 
			
		||||
                 (!
 | 
			
		||||
                  (or (<= (+ a0 (* -1 (?eClosedTime e))) 0)
 | 
			
		||||
                  (or (<= (+ a0 (* (- 1) (?eClosedTime e))) 0)
 | 
			
		||||
                      (not (?isAllocated_ a a0))
 | 
			
		||||
                      (?isAllocated_ (?select (?select e a) i) a0))
 | 
			
		||||
                  :pattern (?isAllocated_ (?select (?select e a) i) a0))))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,7 @@ class recurse_expr : public Visitor {
 | 
			
		|||
    vector<T, CallDestructors>                m_results2;
 | 
			
		||||
 | 
			
		||||
    bool is_cached(expr * n) const { T c; return m_cache.find(n, c); }
 | 
			
		||||
    T get_cached(expr * n) const { T c; m_cache.find(n, c); return c; }
 | 
			
		||||
    T get_cached(expr * n) const { return m_cache.find(n); }
 | 
			
		||||
    void cache_result(expr * n, T c) { m_cache.insert(n, c); }
 | 
			
		||||
    
 | 
			
		||||
    void visit(expr * n, bool & visited);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -118,7 +118,7 @@ public:
 | 
			
		|||
 | 
			
		||||
    void mk_eq(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		||||
        if (mk_eq_core(arg1, arg2, result) == BR_FAILED)
 | 
			
		||||
            result = m_util.mk_le(arg1, arg2);
 | 
			
		||||
            result = m_util.mk_eq(arg1, arg2);
 | 
			
		||||
    }
 | 
			
		||||
    void mk_le(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		||||
        if (mk_le_core(arg1, arg2, result) == BR_FAILED)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,7 @@ void array_rewriter::updt_params(params_ref const & _p) {
 | 
			
		|||
    array_rewriter_params p(_p);
 | 
			
		||||
    m_sort_store = p.sort_store();
 | 
			
		||||
    m_expand_select_store = p.expand_select_store();
 | 
			
		||||
    m_expand_store_eq = p.expand_store_eq();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void array_rewriter::get_param_descrs(param_descrs & r) {
 | 
			
		||||
| 
						 | 
				
			
			@ -365,3 +366,40 @@ br_status array_rewriter::mk_set_subset(expr * arg1, expr * arg2, expr_ref & res
 | 
			
		|||
    return BR_REWRITE3;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status array_rewriter::mk_eq_core(expr * lhs, expr * rhs, expr_ref & result) {
 | 
			
		||||
    if (!m_expand_store_eq) {
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
    expr* lhs1 = lhs;
 | 
			
		||||
    while (m_util.is_store(lhs1)) {
 | 
			
		||||
        lhs1 = to_app(lhs1)->get_arg(0);
 | 
			
		||||
    }
 | 
			
		||||
    expr* rhs1 = rhs;
 | 
			
		||||
    while (m_util.is_store(rhs1)) {
 | 
			
		||||
        rhs1 = to_app(rhs1)->get_arg(0);
 | 
			
		||||
    }
 | 
			
		||||
    if (lhs1 != rhs1) {
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
    ptr_buffer<expr> fmls, args;
 | 
			
		||||
    expr* e;
 | 
			
		||||
    expr_ref tmp1(m()), tmp2(m());
 | 
			
		||||
#define MK_EQ()                                                         \
 | 
			
		||||
    while (m_util.is_store(e)) {                                        \
 | 
			
		||||
        args.push_back(lhs);                                            \
 | 
			
		||||
        args.append(to_app(e)->get_num_args()-2,to_app(e)->get_args()+1); \
 | 
			
		||||
        mk_select(args.size(), args.c_ptr(), tmp1);                     \
 | 
			
		||||
        args[0] = rhs;                                                  \
 | 
			
		||||
        mk_select(args.size(), args.c_ptr(), tmp2);                     \
 | 
			
		||||
        fmls.push_back(m().mk_eq(tmp1, tmp2));                          \
 | 
			
		||||
        e = to_app(e)->get_arg(0);                                      \
 | 
			
		||||
        args.reset();                                                   \
 | 
			
		||||
    }                                                \
 | 
			
		||||
    
 | 
			
		||||
    e = lhs;
 | 
			
		||||
    MK_EQ();
 | 
			
		||||
    e = rhs;
 | 
			
		||||
    MK_EQ();
 | 
			
		||||
    result = m().mk_and(fmls.size(), fmls.c_ptr());
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -31,12 +31,14 @@ class array_rewriter {
 | 
			
		|||
    array_util    m_util;
 | 
			
		||||
    bool          m_sort_store;
 | 
			
		||||
    bool          m_expand_select_store;
 | 
			
		||||
    bool          m_expand_store_eq;
 | 
			
		||||
    template<bool CHECK_DISEQ>
 | 
			
		||||
    lbool compare_args(unsigned num_args, expr * const * args1, expr * const * args2);
 | 
			
		||||
public:    
 | 
			
		||||
    array_rewriter(ast_manager & m, params_ref const & p = params_ref()):
 | 
			
		||||
        m_util(m) {
 | 
			
		||||
        updt_params(p);
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
    ast_manager & m() const { return m_util.get_manager(); }
 | 
			
		||||
    family_id get_fid() const { return m_util.get_family_id(); }
 | 
			
		||||
| 
						 | 
				
			
			@ -60,6 +62,7 @@ public:
 | 
			
		|||
    br_status mk_set_complement(expr * arg, expr_ref & result);
 | 
			
		||||
    br_status mk_set_difference(expr * arg1, expr * arg2, expr_ref & result);
 | 
			
		||||
    br_status mk_set_subset(expr * arg1, expr * arg2, expr_ref & result);
 | 
			
		||||
    br_status mk_eq_core(expr * lhs, expr * rhs, expr_ref & result);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,4 +2,5 @@ def_module_params(module_name='rewriter',
 | 
			
		|||
                  class_name='array_rewriter_params',
 | 
			
		||||
                  export=True,
 | 
			
		||||
                  params=(("expand_select_store", BOOL, False, "replace a (select (store ...) ...) term by an if-then-else term"),
 | 
			
		||||
			  ("expand_store_eq", BOOL, False, "reduce (store ...) = (store ...) with a common base into selects"),
 | 
			
		||||
                          ("sort_store", BOOL, False, "sort nested stores when the indices are known to be different")))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										175
									
								
								src/ast/rewriter/ast_counter.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										175
									
								
								src/ast/rewriter/ast_counter.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,175 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2013 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    ast_counter.cpp
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Routines for counting features of terms, such as free variables.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2013-03-18.
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
#include "ast_counter.h"
 | 
			
		||||
#include "var_subst.h"
 | 
			
		||||
 | 
			
		||||
void counter::update(unsigned el, int delta) {
 | 
			
		||||
    int & counter = get(el);
 | 
			
		||||
    SASSERT(!m_stay_non_negative || counter>=0);
 | 
			
		||||
    SASSERT(!m_stay_non_negative || static_cast<int>(counter)>=-delta);
 | 
			
		||||
    counter += delta;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int & counter::get(unsigned el) {
 | 
			
		||||
    return m_data.insert_if_not_there2(el, 0)->get_data().m_value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
counter & counter::count(unsigned sz, const unsigned * els, int delta) {
 | 
			
		||||
    for(unsigned i=0; i<sz; i++) {
 | 
			
		||||
        update(els[i], delta);
 | 
			
		||||
    }
 | 
			
		||||
    return *this;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned counter::get_positive_count() const {
 | 
			
		||||
    unsigned cnt = 0;
 | 
			
		||||
    iterator eit = begin();
 | 
			
		||||
    iterator eend = end();
 | 
			
		||||
    for(; eit!=eend; ++eit) {
 | 
			
		||||
        if( eit->m_value>0 ) { 
 | 
			
		||||
            cnt++;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return cnt;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void counter::collect_positive(uint_set & acc) const {
 | 
			
		||||
    iterator eit = begin();
 | 
			
		||||
    iterator eend = end();
 | 
			
		||||
    for(; eit!=eend; ++eit) {
 | 
			
		||||
        if(eit->m_value>0) { acc.insert(eit->m_key); }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool counter::get_max_positive(unsigned & res) const {
 | 
			
		||||
    bool found = false;
 | 
			
		||||
    iterator eit = begin();
 | 
			
		||||
    iterator eend = end();
 | 
			
		||||
    for(; eit!=eend; ++eit) {
 | 
			
		||||
        if( eit->m_value>0 && (!found || eit->m_key>res) ) { 
 | 
			
		||||
            found = true;
 | 
			
		||||
            res = eit->m_key;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return found;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned counter::get_max_positive() const {
 | 
			
		||||
    unsigned max_pos;
 | 
			
		||||
    VERIFY(get_max_positive(max_pos));
 | 
			
		||||
    return max_pos;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
int counter::get_max_counter_value() const {
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    iterator eit = begin();
 | 
			
		||||
    iterator eend = end();
 | 
			
		||||
    for (; eit!=eend; ++eit) {
 | 
			
		||||
        if( eit->m_value>res ) { 
 | 
			
		||||
            res = eit->m_value;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void var_counter::count_vars(ast_manager & m, const app * pred, int coef) {
 | 
			
		||||
    unsigned n = pred->get_num_args();
 | 
			
		||||
    for (unsigned i = 0; i < n; i++) {
 | 
			
		||||
        m_sorts.reset();
 | 
			
		||||
        m_todo.reset();
 | 
			
		||||
        m_mark.reset();
 | 
			
		||||
        ::get_free_vars(m_mark, m_todo, pred->get_arg(i), m_sorts);
 | 
			
		||||
        for (unsigned j = 0; j < m_sorts.size(); ++j) {
 | 
			
		||||
            if (m_sorts[j]) {
 | 
			
		||||
                update(j, coef);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
unsigned var_counter::get_max_var(bool& has_var) {
 | 
			
		||||
    has_var = false;
 | 
			
		||||
    unsigned max_var = 0;
 | 
			
		||||
    ptr_vector<quantifier> qs;
 | 
			
		||||
    while (!m_todo.empty()) {
 | 
			
		||||
        expr* e = m_todo.back();
 | 
			
		||||
        m_todo.pop_back();
 | 
			
		||||
        if (m_visited.is_marked(e)) {
 | 
			
		||||
            continue;
 | 
			
		||||
        }
 | 
			
		||||
        m_visited.mark(e, true);
 | 
			
		||||
        switch(e->get_kind()) {
 | 
			
		||||
        case AST_QUANTIFIER: {
 | 
			
		||||
            qs.push_back(to_quantifier(e));
 | 
			
		||||
            break;                 
 | 
			
		||||
        }
 | 
			
		||||
        case AST_VAR: {
 | 
			
		||||
            if (to_var(e)->get_idx() >= max_var) {
 | 
			
		||||
                has_var = true;
 | 
			
		||||
                max_var = to_var(e)->get_idx();
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case AST_APP: {
 | 
			
		||||
            app* a = to_app(e);
 | 
			
		||||
            for (unsigned i = 0; i < a->get_num_args(); ++i) {
 | 
			
		||||
                m_todo.push_back(a->get_arg(i));
 | 
			
		||||
            }
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        default:
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    m_visited.reset();
 | 
			
		||||
 | 
			
		||||
    while (!qs.empty()) {
 | 
			
		||||
        var_counter aux_counter;
 | 
			
		||||
        quantifier* q = qs.back();
 | 
			
		||||
        qs.pop_back();
 | 
			
		||||
        aux_counter.m_todo.push_back(q->get_expr());
 | 
			
		||||
        bool has_var1 = false;
 | 
			
		||||
        unsigned max_v = aux_counter.get_max_var(has_var1);
 | 
			
		||||
        if (max_v >= max_var + q->get_num_decls()) {
 | 
			
		||||
            max_var = max_v - q->get_num_decls();
 | 
			
		||||
            has_var = has_var || has_var1;                
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return max_var;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
unsigned var_counter::get_max_var(expr* e) {
 | 
			
		||||
    bool has_var = false;
 | 
			
		||||
    m_todo.push_back(e);
 | 
			
		||||
    return get_max_var(has_var);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned var_counter::get_next_var(expr* e) {
 | 
			
		||||
    bool has_var = false;
 | 
			
		||||
    m_todo.push_back(e);
 | 
			
		||||
    unsigned mv = get_max_var(has_var);
 | 
			
		||||
    if (has_var) mv++;
 | 
			
		||||
    return mv;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										109
									
								
								src/ast/rewriter/ast_counter.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										109
									
								
								src/ast/rewriter/ast_counter.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,109 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2013 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    ast_counter.h
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Routines for counting features of terms, such as free variables.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2013-03-18.
 | 
			
		||||
    Krystof Hoder (t-khoder) 2010-10-10.
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
    Hoisted from dl_util.h 2013-03-18.
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#ifndef _AST_COUNTER_H_
 | 
			
		||||
#define _AST_COUNTER_H_
 | 
			
		||||
 | 
			
		||||
#include "ast.h"
 | 
			
		||||
#include "map.h"
 | 
			
		||||
#include "uint_set.h"
 | 
			
		||||
 | 
			
		||||
class counter {
 | 
			
		||||
protected:
 | 
			
		||||
    typedef u_map<int> map_impl;
 | 
			
		||||
    map_impl m_data;
 | 
			
		||||
    const bool m_stay_non_negative;
 | 
			
		||||
public:
 | 
			
		||||
    typedef map_impl::iterator iterator;
 | 
			
		||||
    
 | 
			
		||||
    counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {}
 | 
			
		||||
    
 | 
			
		||||
    void reset() { m_data.reset(); }
 | 
			
		||||
    iterator begin() const { return m_data.begin(); }
 | 
			
		||||
    iterator end() const { return m_data.end(); }    
 | 
			
		||||
    void update(unsigned el, int delta);
 | 
			
		||||
    int & get(unsigned el);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Increase values of elements in \c els by \c delta.
 | 
			
		||||
       
 | 
			
		||||
       The function returns a reference to \c *this to allow for expressions like
 | 
			
		||||
       counter().count(sz, arr).get_positive_count()
 | 
			
		||||
    */
 | 
			
		||||
    counter & count(unsigned sz, const unsigned * els, int delta = 1);
 | 
			
		||||
    counter & count(const unsigned_vector & els, int delta = 1) {
 | 
			
		||||
        return count(els.size(), els.c_ptr(), delta);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void collect_positive(uint_set & acc) const;
 | 
			
		||||
    unsigned get_positive_count() const;
 | 
			
		||||
 | 
			
		||||
    bool get_max_positive(unsigned & res) const;
 | 
			
		||||
    unsigned get_max_positive() const;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       Since the default counter value of a counter is zero, the result is never negative.
 | 
			
		||||
    */
 | 
			
		||||
    int get_max_counter_value() const;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class var_counter : public counter {
 | 
			
		||||
protected:
 | 
			
		||||
    ptr_vector<sort> m_sorts;
 | 
			
		||||
    expr_fast_mark1  m_visited;
 | 
			
		||||
    ptr_vector<expr> m_todo;
 | 
			
		||||
    ast_mark         m_mark;
 | 
			
		||||
    unsigned_vector  m_scopes;
 | 
			
		||||
    unsigned get_max_var(bool & has_var);    
 | 
			
		||||
public:
 | 
			
		||||
    var_counter(bool stay_non_negative = true): counter(stay_non_negative) {}
 | 
			
		||||
    void count_vars(ast_manager & m, const app * t, int coef = 1);
 | 
			
		||||
    unsigned get_max_var(expr* e);
 | 
			
		||||
    unsigned get_next_var(expr* e);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class ast_counter {
 | 
			
		||||
    typedef obj_map<ast, int> map_impl;
 | 
			
		||||
    map_impl m_data;
 | 
			
		||||
    bool     m_stay_non_negative;
 | 
			
		||||
 public:
 | 
			
		||||
    typedef map_impl::iterator iterator;
 | 
			
		||||
    
 | 
			
		||||
    ast_counter(bool stay_non_negative = true) : m_stay_non_negative(stay_non_negative) {}
 | 
			
		||||
    
 | 
			
		||||
    iterator begin() const { return m_data.begin(); }
 | 
			
		||||
    iterator end() const { return m_data.end(); }
 | 
			
		||||
    
 | 
			
		||||
    int & get(ast * el) {
 | 
			
		||||
        return m_data.insert_if_not_there2(el, 0)->get_data().m_value;
 | 
			
		||||
    }
 | 
			
		||||
    void update(ast * el, int delta){
 | 
			
		||||
        get(el) += delta;
 | 
			
		||||
        SASSERT(!m_stay_non_negative || get(el) >= 0);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void inc(ast * el) { update(el, 1); }
 | 
			
		||||
    void dec(ast * el) { update(el, -1); }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -64,6 +64,7 @@ void bv_rewriter::updt_local_params(params_ref const & _p) {
 | 
			
		|||
    m_split_concat_eq = p.split_concat_eq();
 | 
			
		||||
    m_udiv2mul = p.udiv2mul();
 | 
			
		||||
    m_bvnot2arith = p.bvnot2arith();
 | 
			
		||||
    m_bv_sort_ac = p.bv_sort_ac();
 | 
			
		||||
    m_mkbv2num = _p.get_bool("mkbv2num", false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1315,7 +1316,7 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re
 | 
			
		|||
        return BR_REWRITE2;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if (!flattened && !merged && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero()))) {
 | 
			
		||||
    if (!flattened && !merged && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero())) && (!m_bv_sort_ac || is_sorted(num, args))) {
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -1331,6 +1332,8 @@ br_status bv_rewriter::mk_bv_or(unsigned num, expr * const * args, expr_ref & re
 | 
			
		|||
        result = new_args[0];
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    default:
 | 
			
		||||
        if (m_bv_sort_ac)
 | 
			
		||||
            std::sort(new_args.begin(), new_args.end(), ast_to_lt());
 | 
			
		||||
        result = m_util.mk_bv_or(new_args.size(), new_args.c_ptr());
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1456,7 +1459,8 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r
 | 
			
		|||
        return BR_REWRITE3;
 | 
			
		||||
    } 
 | 
			
		||||
 | 
			
		||||
    if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1)))))
 | 
			
		||||
    if (!merged && !flattened && (num_coeffs == 0 || (num_coeffs == 1 && !v1.is_zero() && v1 != (rational::power_of_two(sz) - numeral(1)))) &&
 | 
			
		||||
        (!m_bv_sort_ac || is_sorted(num, args)))
 | 
			
		||||
        return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
    ptr_buffer<expr> new_args;
 | 
			
		||||
| 
						 | 
				
			
			@ -1497,6 +1501,8 @@ br_status bv_rewriter::mk_bv_xor(unsigned num, expr * const * args, expr_ref & r
 | 
			
		|||
        }
 | 
			
		||||
        __fallthrough;
 | 
			
		||||
    default:
 | 
			
		||||
        if (m_bv_sort_ac)
 | 
			
		||||
            std::sort(new_args.begin(), new_args.end(), ast_to_lt());
 | 
			
		||||
        result = m_util.mk_bv_xor(new_args.size(), new_args.c_ptr());
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,7 @@ class bv_rewriter : public poly_rewriter<bv_rewriter_core> {
 | 
			
		|||
    bool       m_split_concat_eq;
 | 
			
		||||
    bool       m_udiv2mul;
 | 
			
		||||
    bool       m_bvnot2arith;
 | 
			
		||||
    bool       m_bv_sort_ac;
 | 
			
		||||
 | 
			
		||||
    bool is_zero_bit(expr * x, unsigned idx);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -8,5 +8,6 @@ def_module_params(module_name='rewriter',
 | 
			
		|||
                          ("elim_sign_ext", BOOL, True, "expand sign-ext operator using concat and extract"),
 | 
			
		||||
                          ("hi_div0", BOOL, True, "use the 'hardware interpretation' for division by zero (for bit-vector terms)"),
 | 
			
		||||
                          ("mul2concat", BOOL, False, "replace multiplication by a power of two into a concatenation"),
 | 
			
		||||
                          ("bvnot2arith", BOOL, False, "replace (bvnot x) with (bvsub -1 x)")
 | 
			
		||||
                          ("bvnot2arith", BOOL, False, "replace (bvnot x) with (bvsub -1 x)"),
 | 
			
		||||
                          ("bv_sort_ac", BOOL, False, "sort the arguments of all AC operators")
 | 
			
		||||
                          ))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -100,3 +100,16 @@ void expr_safe_replace::operator()(expr* e, expr_ref& res) {
 | 
			
		|||
    }
 | 
			
		||||
    res = cache.find(e);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void expr_safe_replace::reset() {
 | 
			
		||||
    m_src.reset();
 | 
			
		||||
    m_dst.reset();
 | 
			
		||||
    m_subst.reset();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void expr_safe_replace::apply_substitution(expr* s, expr* def, expr_ref& t) {
 | 
			
		||||
    reset();
 | 
			
		||||
    insert(s, def);
 | 
			
		||||
    (*this)(t, t);
 | 
			
		||||
    reset();
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -38,6 +38,10 @@ public:
 | 
			
		|||
    void operator()(expr_ref& e) { (*this)(e.get(), e); }
 | 
			
		||||
 | 
			
		||||
    void operator()(expr* src, expr_ref& e);
 | 
			
		||||
 | 
			
		||||
    void apply_substitution(expr* s, expr* def, expr_ref& t);
 | 
			
		||||
 | 
			
		||||
    void reset();
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif /* __EXPR_SAFE_REPLACE_H__ */
 | 
			
		||||
| 
						 | 
				
			
			@ -58,6 +58,10 @@ br_status float_rewriter::mk_app_core(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
    case OP_FLOAT_IS_ZERO:   SASSERT(num_args == 1); st = mk_is_zero(args[0], result); break;
 | 
			
		||||
    case OP_FLOAT_IS_NZERO:  SASSERT(num_args == 1); st = mk_is_nzero(args[0], result); break;
 | 
			
		||||
    case OP_FLOAT_IS_PZERO:  SASSERT(num_args == 1); st = mk_is_pzero(args[0], result); break;
 | 
			
		||||
    case OP_FLOAT_IS_NAN:    SASSERT(num_args == 1); st = mk_is_nan(args[0], result); break;
 | 
			
		||||
    case OP_FLOAT_IS_INF:    SASSERT(num_args == 1); st = mk_is_inf(args[0], result); break;
 | 
			
		||||
    case OP_FLOAT_IS_NORMAL: SASSERT(num_args == 1); st = mk_is_normal(args[0], result); break;
 | 
			
		||||
    case OP_FLOAT_IS_SUBNORMAL: SASSERT(num_args == 1); st = mk_is_subnormal(args[0], result); break;
 | 
			
		||||
    case OP_FLOAT_IS_SIGN_MINUS: SASSERT(num_args == 1); st = mk_is_sign_minus(args[0], result); break;
 | 
			
		||||
    case OP_TO_IEEE_BV:      SASSERT(num_args == 1); st = mk_to_ieee_bv(args[0], result); break;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -77,14 +81,27 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
            return BR_FAILED;
 | 
			
		||||
        
 | 
			
		||||
        rational q;
 | 
			
		||||
        if (!m_util.au().is_numeral(args[1], q))
 | 
			
		||||
        mpf q_mpf;
 | 
			
		||||
        if (m_util.au().is_numeral(args[1], q)) {        
 | 
			
		||||
            TRACE("fp_rewriter", tout << "q: " << q << std::endl; );
 | 
			
		||||
            mpf v;
 | 
			
		||||
            m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
 | 
			
		||||
            result = m_util.mk_value(v);
 | 
			
		||||
            m_util.fm().del(v);
 | 
			
		||||
            // TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
        else if (m_util.is_value(args[1], q_mpf)) {
 | 
			
		||||
            TRACE("fp_rewriter", tout << "q: " << m_util.fm().to_string(q_mpf) << std::endl; );
 | 
			
		||||
            mpf v;
 | 
			
		||||
            m_util.fm().set(v, ebits, sbits, rm, q_mpf);
 | 
			
		||||
            result = m_util.mk_value(v);
 | 
			
		||||
            m_util.fm().del(v);
 | 
			
		||||
            // TRACE("fp_rewriter", tout << "result: " << result << std::endl; );
 | 
			
		||||
            return BR_DONE;
 | 
			
		||||
        }
 | 
			
		||||
        else 
 | 
			
		||||
            return BR_FAILED;
 | 
			
		||||
        
 | 
			
		||||
        mpf v;
 | 
			
		||||
        m_util.fm().set(v, ebits, sbits, rm, q.to_mpq());
 | 
			
		||||
        result = m_util.mk_value(v);
 | 
			
		||||
        m_util.fm().del(v);
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    else if (num_args == 3 && 
 | 
			
		||||
             m_util.is_rm(m().get_sort(args[0])) && 
 | 
			
		||||
| 
						 | 
				
			
			@ -104,11 +121,11 @@ br_status float_rewriter::mk_to_float(func_decl * f, unsigned num_args, expr * c
 | 
			
		|||
            return BR_FAILED;
 | 
			
		||||
 | 
			
		||||
        TRACE("fp_rewriter", tout << "q: " << q << ", e: " << e << "\n";);
 | 
			
		||||
 | 
			
		||||
        mpf v;
 | 
			
		||||
	    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 {
 | 
			
		||||
| 
						 | 
				
			
			@ -217,8 +234,7 @@ br_status float_rewriter::mk_abs(expr * arg1, expr_ref & result) {
 | 
			
		|||
        result = arg1;
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    sort * s = m().get_sort(arg1);
 | 
			
		||||
    result = m().mk_ite(m_util.mk_lt(arg1, m_util.mk_pzero(s)),
 | 
			
		||||
    result = m().mk_ite(m_util.mk_is_sign_minus(arg1),
 | 
			
		||||
                        m_util.mk_uminus(arg1),
 | 
			
		||||
                        arg1);
 | 
			
		||||
    return BR_REWRITE2;
 | 
			
		||||
| 
						 | 
				
			
			@ -234,13 +250,13 @@ br_status float_rewriter::mk_min(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		|||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    // expand as using ite's
 | 
			
		||||
    result = m().mk_ite(mk_eq_nan(arg1),
 | 
			
		||||
    result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
 | 
			
		||||
                        arg2,
 | 
			
		||||
                        m().mk_ite(mk_eq_nan(arg2), 
 | 
			
		||||
                                   arg1,
 | 
			
		||||
                                   m().mk_ite(m_util.mk_lt(arg1, arg2),
 | 
			
		||||
                                              arg1,
 | 
			
		||||
                                              arg2)));
 | 
			
		||||
                                           arg1,
 | 
			
		||||
                                           arg2)));
 | 
			
		||||
    return BR_REWRITE_FULL;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -254,7 +270,7 @@ br_status float_rewriter::mk_max(expr * arg1, expr * arg2, expr_ref & result) {
 | 
			
		|||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
    // expand as using ite's
 | 
			
		||||
    result = m().mk_ite(mk_eq_nan(arg1), 
 | 
			
		||||
    result = m().mk_ite(m().mk_or(mk_eq_nan(arg1), m().mk_and(m_util.mk_is_zero(arg1), m_util.mk_is_zero(arg2))),
 | 
			
		||||
                        arg2,
 | 
			
		||||
                        m().mk_ite(mk_eq_nan(arg2), 
 | 
			
		||||
                                   arg1,
 | 
			
		||||
| 
						 | 
				
			
			@ -420,6 +436,46 @@ br_status float_rewriter::mk_is_pzero(expr * arg1, expr_ref & result) {
 | 
			
		|||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status float_rewriter::mk_is_nan(expr * arg1, expr_ref & result) {
 | 
			
		||||
    scoped_mpf v(m_util.fm());
 | 
			
		||||
    if (m_util.is_value(arg1, v)) {
 | 
			
		||||
        result = (m_util.fm().is_nan(v)) ? m().mk_true() : m().mk_false();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status float_rewriter::mk_is_inf(expr * arg1, expr_ref & result) {
 | 
			
		||||
    scoped_mpf v(m_util.fm());
 | 
			
		||||
    if (m_util.is_value(arg1, v)) {
 | 
			
		||||
        result = (m_util.fm().is_inf(v)) ? m().mk_true() : m().mk_false();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status float_rewriter::mk_is_normal(expr * arg1, expr_ref & result) {
 | 
			
		||||
    scoped_mpf v(m_util.fm());
 | 
			
		||||
    if (m_util.is_value(arg1, v)) {
 | 
			
		||||
        result = (m_util.fm().is_normal(v)) ? m().mk_true() : m().mk_false();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status float_rewriter::mk_is_subnormal(expr * arg1, expr_ref & result) {
 | 
			
		||||
    scoped_mpf v(m_util.fm());
 | 
			
		||||
    if (m_util.is_value(arg1, v)) {
 | 
			
		||||
        result = (m_util.fm().is_denormal(v)) ? m().mk_true() : m().mk_false();
 | 
			
		||||
        return BR_DONE;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return BR_FAILED;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
br_status float_rewriter::mk_is_sign_minus(expr * arg1, expr_ref & result) {
 | 
			
		||||
    scoped_mpf v(m_util.fm());
 | 
			
		||||
    if (m_util.is_value(arg1, v)) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -66,6 +66,10 @@ public:
 | 
			
		|||
    br_status mk_is_zero(expr * arg1, expr_ref & result);
 | 
			
		||||
    br_status mk_is_nzero(expr * arg1, expr_ref & result);
 | 
			
		||||
    br_status mk_is_pzero(expr * arg1, expr_ref & result);
 | 
			
		||||
    br_status mk_is_nan(expr * arg1, expr_ref & result);
 | 
			
		||||
    br_status mk_is_inf(expr * arg1, expr_ref & result);
 | 
			
		||||
    br_status mk_is_normal(expr * arg1, expr_ref & result);
 | 
			
		||||
    br_status mk_is_subnormal(expr * arg1, expr_ref & result);
 | 
			
		||||
    br_status mk_is_sign_minus(expr * arg1, expr_ref & result);
 | 
			
		||||
 | 
			
		||||
    br_status mk_to_ieee_bv(expr * arg1, expr_ref & result);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -62,6 +62,8 @@ struct mk_simplified_app::imp {
 | 
			
		|||
                    st = m_dt_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                else if (s_fid == m_f_rw.get_fid())
 | 
			
		||||
                    st = m_f_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                else if (s_fid == m_ar_rw.get_fid())
 | 
			
		||||
                    st = m_ar_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                
 | 
			
		||||
                if (st != BR_FAILED)
 | 
			
		||||
                    return st;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,8 @@ Revision History:
 | 
			
		|||
#include "bool_rewriter.h"
 | 
			
		||||
#include "var_subst.h"
 | 
			
		||||
#include "ast_pp.h"
 | 
			
		||||
 | 
			
		||||
#include "ast_counter.h"
 | 
			
		||||
#include "expr_safe_replace.h"
 | 
			
		||||
 | 
			
		||||
//
 | 
			
		||||
// Bring quantifiers of common type into prenex form.
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +43,7 @@ public:
 | 
			
		|||
    
 | 
			
		||||
    void operator()(expr* fml, app_ref_vector& vars, bool& is_fa, expr_ref& result) {
 | 
			
		||||
        quantifier_type qt = Q_none_pos;
 | 
			
		||||
        pull_quantifiers(fml, qt, vars, result);
 | 
			
		||||
        pull_quantifier(fml, qt, vars, result);
 | 
			
		||||
        TRACE("qe_verbose", 
 | 
			
		||||
              tout << mk_pp(fml, m) << "\n";
 | 
			
		||||
              tout << mk_pp(result, m) << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			@ -52,7 +53,7 @@ public:
 | 
			
		|||
    
 | 
			
		||||
    void pull_exists(expr* fml, app_ref_vector& vars, expr_ref& result) {
 | 
			
		||||
        quantifier_type qt = Q_exists_pos;
 | 
			
		||||
        pull_quantifiers(fml, qt, vars, result);
 | 
			
		||||
        pull_quantifier(fml, qt, vars, result);
 | 
			
		||||
        TRACE("qe_verbose", 
 | 
			
		||||
              tout << mk_pp(fml, m) << "\n";
 | 
			
		||||
              tout << mk_pp(result, m) << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			@ -61,7 +62,7 @@ public:
 | 
			
		|||
    void pull_quantifier(bool is_forall, expr_ref& fml, app_ref_vector& vars) {
 | 
			
		||||
        quantifier_type qt = is_forall?Q_forall_pos:Q_exists_pos;
 | 
			
		||||
        expr_ref result(m);
 | 
			
		||||
        pull_quantifiers(fml, qt, vars, result);
 | 
			
		||||
        pull_quantifier(fml, qt, vars, result);
 | 
			
		||||
        TRACE("qe_verbose", 
 | 
			
		||||
              tout << mk_pp(fml, m) << "\n";
 | 
			
		||||
              tout << mk_pp(result, m) << "\n";);
 | 
			
		||||
| 
						 | 
				
			
			@ -79,6 +80,56 @@ public:
 | 
			
		|||
        instantiate(m, q, exprs, result);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names) {
 | 
			
		||||
        unsigned index = var_counter().get_next_var(fml);
 | 
			
		||||
        while (is_quantifier(fml) && (is_forall == to_quantifier(fml)->is_forall())) {
 | 
			
		||||
            quantifier* q = to_quantifier(fml);
 | 
			
		||||
            index += q->get_num_decls();
 | 
			
		||||
            if (names) {
 | 
			
		||||
                names->append(q->get_num_decls(), q->get_decl_names());
 | 
			
		||||
            }
 | 
			
		||||
            if (sorts) {
 | 
			
		||||
                sorts->append(q->get_num_decls(), q->get_decl_sorts());
 | 
			
		||||
            }
 | 
			
		||||
            fml = q->get_expr();
 | 
			
		||||
        }
 | 
			
		||||
        if (!has_quantifiers(fml)) {
 | 
			
		||||
            return index;
 | 
			
		||||
        }
 | 
			
		||||
        app_ref_vector vars(m);
 | 
			
		||||
        pull_quantifier(is_forall, fml, vars);
 | 
			
		||||
        if (vars.empty()) {
 | 
			
		||||
            return index;
 | 
			
		||||
        }
 | 
			
		||||
        // replace vars by de-bruijn indices
 | 
			
		||||
        expr_safe_replace rep(m);
 | 
			
		||||
        svector<symbol> bound_names;
 | 
			
		||||
        ptr_vector<sort> bound_sorts;
 | 
			
		||||
        for (unsigned i = 0; i < vars.size(); ++i) {
 | 
			
		||||
            app* v = vars[i].get();
 | 
			
		||||
            if (names) {
 | 
			
		||||
                bound_names.push_back(v->get_decl()->get_name());
 | 
			
		||||
            }                
 | 
			
		||||
            if (sorts) {
 | 
			
		||||
                bound_sorts.push_back(m.get_sort(v));
 | 
			
		||||
            }
 | 
			
		||||
            rep.insert(v, m.mk_var(index++, m.get_sort(v)));
 | 
			
		||||
        }
 | 
			
		||||
        if (names && !bound_names.empty()) {
 | 
			
		||||
            bound_names.reverse();
 | 
			
		||||
            bound_names.append(*names);
 | 
			
		||||
            names->reset();
 | 
			
		||||
            names->append(bound_names);
 | 
			
		||||
        }
 | 
			
		||||
        if (sorts && !bound_sorts.empty()) {
 | 
			
		||||
            bound_sorts.reverse();
 | 
			
		||||
            bound_sorts.append(*sorts);
 | 
			
		||||
            sorts->reset();
 | 
			
		||||
            sorts->append(bound_sorts);
 | 
			
		||||
        }
 | 
			
		||||
        rep(fml);
 | 
			
		||||
        return index;
 | 
			
		||||
    }    
 | 
			
		||||
    
 | 
			
		||||
private:
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +194,7 @@ private:
 | 
			
		|||
    }
 | 
			
		||||
    
 | 
			
		||||
    
 | 
			
		||||
    void pull_quantifiers(expr* fml, quantifier_type& qt, app_ref_vector& vars, expr_ref& result) {
 | 
			
		||||
    void pull_quantifier(expr* fml, quantifier_type& qt, app_ref_vector& vars, expr_ref& result) {
 | 
			
		||||
        
 | 
			
		||||
        if (!has_quantifiers(fml)) {
 | 
			
		||||
            result = fml;
 | 
			
		||||
| 
						 | 
				
			
			@ -159,7 +210,7 @@ private:
 | 
			
		|||
            if (m.is_and(fml)) {
 | 
			
		||||
                num_args = a->get_num_args();
 | 
			
		||||
                for (unsigned i = 0; i < num_args; ++i) {
 | 
			
		||||
                    pull_quantifiers(a->get_arg(i), qt, vars, tmp);
 | 
			
		||||
                    pull_quantifier(a->get_arg(i), qt, vars, tmp);
 | 
			
		||||
                    args.push_back(tmp);
 | 
			
		||||
                }
 | 
			
		||||
                m_rewriter.mk_and(args.size(), args.c_ptr(), result);
 | 
			
		||||
| 
						 | 
				
			
			@ -167,25 +218,25 @@ private:
 | 
			
		|||
            else if (m.is_or(fml)) {
 | 
			
		||||
                num_args = to_app(fml)->get_num_args();
 | 
			
		||||
                for (unsigned i = 0; i < num_args; ++i) {
 | 
			
		||||
                    pull_quantifiers(to_app(fml)->get_arg(i), qt, vars, tmp);
 | 
			
		||||
                    pull_quantifier(to_app(fml)->get_arg(i), qt, vars, tmp);
 | 
			
		||||
                    args.push_back(tmp);
 | 
			
		||||
                }
 | 
			
		||||
                m_rewriter.mk_or(args.size(), args.c_ptr(), result);
 | 
			
		||||
            }
 | 
			
		||||
            else if (m.is_not(fml)) {
 | 
			
		||||
                pull_quantifiers(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
 | 
			
		||||
                pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
 | 
			
		||||
                negate(qt);
 | 
			
		||||
                result = m.mk_not(tmp);
 | 
			
		||||
            }
 | 
			
		||||
            else if (m.is_implies(fml)) {
 | 
			
		||||
                pull_quantifiers(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
 | 
			
		||||
                pull_quantifier(to_app(fml)->get_arg(0), negate(qt), vars, tmp);
 | 
			
		||||
                negate(qt);
 | 
			
		||||
                pull_quantifiers(to_app(fml)->get_arg(1), qt, vars, result);
 | 
			
		||||
                pull_quantifier(to_app(fml)->get_arg(1), qt, vars, result);
 | 
			
		||||
                result = m.mk_implies(tmp, result);
 | 
			
		||||
            }
 | 
			
		||||
            else if (m.is_ite(fml)) {
 | 
			
		||||
                pull_quantifiers(to_app(fml)->get_arg(1), qt, vars, tmp);
 | 
			
		||||
                pull_quantifiers(to_app(fml)->get_arg(2), qt, vars, result);
 | 
			
		||||
                pull_quantifier(to_app(fml)->get_arg(1), qt, vars, tmp);
 | 
			
		||||
                pull_quantifier(to_app(fml)->get_arg(2), qt, vars, result);
 | 
			
		||||
                result = m.mk_ite(to_app(fml)->get_arg(0), tmp, result);
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
| 
						 | 
				
			
			@ -203,7 +254,7 @@ private:
 | 
			
		|||
            }
 | 
			
		||||
            set_quantifier_type(qt, q->is_forall());
 | 
			
		||||
            extract_quantifier(q, vars, tmp);
 | 
			
		||||
            pull_quantifiers(tmp, qt, vars, result);
 | 
			
		||||
            pull_quantifier(tmp, qt, vars, result);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case AST_VAR:
 | 
			
		||||
| 
						 | 
				
			
			@ -215,6 +266,7 @@ private:
 | 
			
		|||
            break;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
};   
 | 
			
		||||
 | 
			
		||||
quantifier_hoister::quantifier_hoister(ast_manager& m) {
 | 
			
		||||
| 
						 | 
				
			
			@ -237,3 +289,6 @@ void quantifier_hoister::pull_quantifier(bool is_forall, expr_ref& fml, app_ref_
 | 
			
		|||
    m_impl->pull_quantifier(is_forall, fml, vars);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
unsigned quantifier_hoister::pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names) {
 | 
			
		||||
    return m_impl->pull_quantifier(is_forall, fml, sorts, names);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -59,6 +59,15 @@ public:
 | 
			
		|||
       The list of variables is empty if there are no top-level universal/existential quantifier.
 | 
			
		||||
    */
 | 
			
		||||
    void pull_quantifier(bool is_forall, expr_ref& fml, app_ref_vector& vars);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Pull top-most universal (is_forall true) or existential (is_forall=false) quantifier up.
 | 
			
		||||
       Return an expression with de-Bruijn indices and the list of names that were used.
 | 
			
		||||
       Return index of maximal variable.
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    unsigned pull_quantifier(bool is_forall, expr_ref& fml, ptr_vector<sort>* sorts, svector<symbol>* names);
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -169,6 +169,8 @@ struct th_rewriter_cfg : public default_rewriter_cfg {
 | 
			
		|||
                    st = m_dt_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                else if (s_fid == m_f_rw.get_fid())
 | 
			
		||||
                    st = m_f_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                else if (s_fid == m_ar_rw.get_fid())
 | 
			
		||||
                    st = m_ar_rw.mk_eq_core(args[0], args[1], result);
 | 
			
		||||
                
 | 
			
		||||
                if (st != BR_FAILED)
 | 
			
		||||
                    return st;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -17,7 +17,6 @@ Notes:
 | 
			
		|||
 | 
			
		||||
--*/
 | 
			
		||||
#include"var_subst.h"
 | 
			
		||||
#include"used_vars.h"
 | 
			
		||||
#include"ast_ll_pp.h"
 | 
			
		||||
#include"ast_pp.h"
 | 
			
		||||
#include"ast_smt2_pp.h"
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +39,7 @@ void var_subst::operator()(expr * n, unsigned num_args, expr * const * args, exp
 | 
			
		|||
          tout << mk_ismt2_pp(result, m_reducer.m()) << "\n";);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		||||
void unused_vars_eliminator::operator()(quantifier* q, expr_ref & result) {
 | 
			
		||||
    SASSERT(is_well_sorted(m, q));
 | 
			
		||||
    if (is_ground(q->get_expr())) {
 | 
			
		||||
        // ignore patterns if the body is a ground formula.
 | 
			
		||||
| 
						 | 
				
			
			@ -51,17 +50,17 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		|||
        result = q;
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
    used_vars used;
 | 
			
		||||
    used.process(q->get_expr());
 | 
			
		||||
    m_used.reset();
 | 
			
		||||
    m_used.process(q->get_expr());
 | 
			
		||||
    unsigned num_patterns = q->get_num_patterns();
 | 
			
		||||
    for (unsigned i = 0; i < num_patterns; i++)
 | 
			
		||||
        used.process(q->get_pattern(i));
 | 
			
		||||
        m_used.process(q->get_pattern(i));
 | 
			
		||||
    unsigned num_no_patterns = q->get_num_no_patterns();
 | 
			
		||||
    for (unsigned i = 0; i < num_no_patterns; i++)
 | 
			
		||||
        used.process(q->get_no_pattern(i));
 | 
			
		||||
        m_used.process(q->get_no_pattern(i));
 | 
			
		||||
 | 
			
		||||
    unsigned num_decls = q->get_num_decls();
 | 
			
		||||
    if (used.uses_all_vars(num_decls)) {
 | 
			
		||||
    if (m_used.uses_all_vars(num_decls)) {
 | 
			
		||||
        q->set_no_unused_vars();
 | 
			
		||||
        result = q;
 | 
			
		||||
        return;
 | 
			
		||||
| 
						 | 
				
			
			@ -70,7 +69,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		|||
    ptr_buffer<sort>  used_decl_sorts; 
 | 
			
		||||
    buffer<symbol>    used_decl_names;
 | 
			
		||||
    for (unsigned i = 0; i < num_decls; ++i) {
 | 
			
		||||
        if (used.contains(num_decls - i - 1)) {
 | 
			
		||||
        if (m_used.contains(num_decls - i - 1)) {
 | 
			
		||||
            used_decl_sorts.push_back(q->get_decl_sort(i));
 | 
			
		||||
            used_decl_names.push_back(q->get_decl_name(i));
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -79,10 +78,10 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		|||
    unsigned         num_removed = 0;
 | 
			
		||||
    expr_ref_buffer  var_mapping(m);
 | 
			
		||||
    int              next_idx = 0;
 | 
			
		||||
    unsigned         sz = used.get_max_found_var_idx_plus_1();
 | 
			
		||||
    unsigned         sz = m_used.get_max_found_var_idx_plus_1();
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = 0; i < num_decls; ++i) {
 | 
			
		||||
        sort * s = used.contains(i);
 | 
			
		||||
        sort * s = m_used.contains(i);
 | 
			
		||||
        if (s) {
 | 
			
		||||
            var_mapping.push_back(m.mk_var(next_idx, s));
 | 
			
		||||
            next_idx++;
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +94,7 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		|||
    // (VAR 0) is in the first position of var_mapping.
 | 
			
		||||
 | 
			
		||||
    for (unsigned i = num_decls; i < sz; i++) {
 | 
			
		||||
        sort * s = used.contains(i);
 | 
			
		||||
        sort * s = m_used.contains(i);
 | 
			
		||||
        if (s)
 | 
			
		||||
            var_mapping.push_back(m.mk_var(i - num_removed, s));
 | 
			
		||||
        else
 | 
			
		||||
| 
						 | 
				
			
			@ -110,9 +109,8 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		|||
    std::reverse(var_mapping.c_ptr(), var_mapping.c_ptr() + var_mapping.size());
 | 
			
		||||
 | 
			
		||||
    expr_ref  new_expr(m);
 | 
			
		||||
    var_subst subst(m);
 | 
			
		||||
    
 | 
			
		||||
    subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
 | 
			
		||||
    m_subst(q->get_expr(), var_mapping.size(), var_mapping.c_ptr(), new_expr);
 | 
			
		||||
    
 | 
			
		||||
    if (num_removed == num_decls) {
 | 
			
		||||
        result = new_expr;
 | 
			
		||||
| 
						 | 
				
			
			@ -124,11 +122,11 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		|||
    expr_ref_buffer new_no_patterns(m);
 | 
			
		||||
    
 | 
			
		||||
    for (unsigned i = 0; i < num_patterns; i++) {
 | 
			
		||||
        subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
 | 
			
		||||
        m_subst(q->get_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
 | 
			
		||||
        new_patterns.push_back(tmp);
 | 
			
		||||
    }
 | 
			
		||||
    for (unsigned i = 0; i < num_no_patterns; i++) {
 | 
			
		||||
        subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
 | 
			
		||||
        m_subst(q->get_no_pattern(i), var_mapping.size(), var_mapping.c_ptr(), tmp);
 | 
			
		||||
        new_no_patterns.push_back(tmp);
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
| 
						 | 
				
			
			@ -148,6 +146,11 @@ void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		|||
    SASSERT(is_well_sorted(m, result));    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & result) {
 | 
			
		||||
    unused_vars_eliminator el(m);
 | 
			
		||||
    el(q, result);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref & result) {
 | 
			
		||||
    var_subst subst(m);
 | 
			
		||||
    expr_ref new_expr(m);
 | 
			
		||||
| 
						 | 
				
			
			@ -161,9 +164,7 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref
 | 
			
		|||
          tout << "\n----->\n" << mk_ismt2_pp(result, m) << "\n";);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sorts) {
 | 
			
		||||
    ast_mark mark;
 | 
			
		||||
    ptr_vector<expr> todo;
 | 
			
		||||
static void get_free_vars_offset(ast_mark& mark, ptr_vector<expr>& todo, unsigned offset, expr* e, ptr_vector<sort>& sorts) {
 | 
			
		||||
    todo.push_back(e);
 | 
			
		||||
    while (!todo.empty()) {
 | 
			
		||||
        e = todo.back();
 | 
			
		||||
| 
						 | 
				
			
			@ -175,7 +176,9 @@ static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sor
 | 
			
		|||
        switch(e->get_kind()) {
 | 
			
		||||
        case AST_QUANTIFIER: {
 | 
			
		||||
            quantifier* q = to_quantifier(e);
 | 
			
		||||
            get_free_vars_offset(q->get_expr(), offset+q->get_num_decls(), sorts);
 | 
			
		||||
            ast_mark mark1;
 | 
			
		||||
            ptr_vector<expr> todo1;
 | 
			
		||||
            get_free_vars_offset(mark1, todo1, offset+q->get_num_decls(), q->get_expr(), sorts);
 | 
			
		||||
            break;
 | 
			
		||||
        }
 | 
			
		||||
        case AST_VAR: {
 | 
			
		||||
| 
						 | 
				
			
			@ -207,5 +210,11 @@ static void get_free_vars_offset(expr* e, unsigned offset, ptr_vector<sort>& sor
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
void get_free_vars(expr* e, ptr_vector<sort>& sorts) {
 | 
			
		||||
    get_free_vars_offset(e, 0, sorts);
 | 
			
		||||
    ast_mark mark;
 | 
			
		||||
    ptr_vector<expr> todo;
 | 
			
		||||
    get_free_vars_offset(mark, todo, 0, e, sorts);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts) {
 | 
			
		||||
    get_free_vars_offset(mark, todo, 0, e, sorts);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -20,6 +20,7 @@ Notes:
 | 
			
		|||
#define _VAR_SUBST_H_
 | 
			
		||||
 | 
			
		||||
#include"rewriter.h"
 | 
			
		||||
#include"used_vars.h"
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
   \brief Alias for var_shifter class.
 | 
			
		||||
| 
						 | 
				
			
			@ -53,6 +54,15 @@ public:
 | 
			
		|||
/**
 | 
			
		||||
   \brief Eliminate the unused variables from \c q. Store the result in \c r.
 | 
			
		||||
*/
 | 
			
		||||
class unused_vars_eliminator {
 | 
			
		||||
    ast_manager& m;
 | 
			
		||||
    var_subst    m_subst;
 | 
			
		||||
    used_vars    m_used;
 | 
			
		||||
public:
 | 
			
		||||
    unused_vars_eliminator(ast_manager& m): m(m), m_subst(m) {}
 | 
			
		||||
    void operator()(quantifier* q, expr_ref& r);
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
void elim_unused_vars(ast_manager & m, quantifier * q, expr_ref & r);
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
| 
						 | 
				
			
			@ -73,6 +83,8 @@ void instantiate(ast_manager & m, quantifier * q, expr * const * exprs, expr_ref
 | 
			
		|||
*/
 | 
			
		||||
void get_free_vars(expr* e, ptr_vector<sort>& sorts);
 | 
			
		||||
 | 
			
		||||
void get_free_vars(ast_mark& mark, ptr_vector<expr>& todo, expr* e, ptr_vector<sort>& sorts);
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										55
									
								
								src/ast/scoped_proof.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										55
									
								
								src/ast/scoped_proof.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,55 @@
 | 
			
		|||
/*++
 | 
			
		||||
Copyright (c) 2013 Microsoft Corporation
 | 
			
		||||
 | 
			
		||||
Module Name:
 | 
			
		||||
 | 
			
		||||
    scoped_proof.h
 | 
			
		||||
 | 
			
		||||
Abstract:
 | 
			
		||||
 | 
			
		||||
    Scoped proof environments. Toggles enabling proofs.
 | 
			
		||||
 | 
			
		||||
Author:
 | 
			
		||||
 | 
			
		||||
    Nikolaj Bjorner (nbjorner) 2013-08-28
 | 
			
		||||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
#ifndef _SCOPED_PROOF__H_
 | 
			
		||||
#define _SCOPED_PROOF_H_
 | 
			
		||||
 | 
			
		||||
#include "ast.h"
 | 
			
		||||
 | 
			
		||||
class scoped_proof_mode {
 | 
			
		||||
    ast_manager&   m;
 | 
			
		||||
    proof_gen_mode m_mode;
 | 
			
		||||
public:
 | 
			
		||||
    scoped_proof_mode(ast_manager& m, proof_gen_mode mode): m(m) {
 | 
			
		||||
        m_mode = m.proof_mode();
 | 
			
		||||
        m.toggle_proof_mode(mode);
 | 
			
		||||
    }
 | 
			
		||||
    ~scoped_proof_mode() {
 | 
			
		||||
            m.toggle_proof_mode(m_mode);            
 | 
			
		||||
        }
 | 
			
		||||
    
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class scoped_proof : public scoped_proof_mode {
 | 
			
		||||
public:
 | 
			
		||||
    scoped_proof(ast_manager& m): scoped_proof_mode(m, PGM_FINE) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class scoped_no_proof : public scoped_proof_mode {
 | 
			
		||||
public:
 | 
			
		||||
    scoped_no_proof(ast_manager& m): scoped_proof_mode(m, PGM_DISABLED) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
class scoped_restore_proof : public scoped_proof_mode {
 | 
			
		||||
public:
 | 
			
		||||
    scoped_restore_proof(ast_manager& m): scoped_proof_mode(m, m.proof_mode()) {}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			@ -636,7 +636,31 @@ bool bv_simplifier_plugin::try_mk_extract(unsigned high, unsigned low, expr * ar
 | 
			
		|||
        if (!all_found) {
 | 
			
		||||
            return false;
 | 
			
		||||
        }
 | 
			
		||||
        result = m_manager.mk_app(m_fid, a->get_decl_kind(), new_args.size(), new_args.c_ptr());
 | 
			
		||||
        // We should not use mk_app because it does not guarantee that the result would be in simplified form.
 | 
			
		||||
        // result = m_manager.mk_app(m_fid, a->get_decl_kind(), new_args.size(), new_args.c_ptr());
 | 
			
		||||
        if (is_app_of(a, m_fid, OP_BAND))
 | 
			
		||||
            mk_bv_and(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BOR))
 | 
			
		||||
            mk_bv_or(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BXOR))
 | 
			
		||||
            mk_bv_xor(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BNOR))
 | 
			
		||||
            mk_bv_nor(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BNAND))
 | 
			
		||||
            mk_bv_nand(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BNOT)) {
 | 
			
		||||
            SASSERT(new_args.size() == 1);
 | 
			
		||||
            mk_bv_not(new_args[0], result);
 | 
			
		||||
        }
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BADD))
 | 
			
		||||
            mk_add(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BMUL))
 | 
			
		||||
            mk_mul(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else if (is_app_of(a, m_fid, OP_BSUB))
 | 
			
		||||
            mk_sub(new_args.size(), new_args.c_ptr(), result);
 | 
			
		||||
        else {
 | 
			
		||||
            UNREACHABLE();
 | 
			
		||||
        }
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
    else if (m_manager.is_ite(a)) {
 | 
			
		||||
| 
						 | 
				
			
			@ -747,16 +771,16 @@ void bv_simplifier_plugin::mk_bv_eq(expr* a1, expr* a2, expr_ref& result) {
 | 
			
		|||
        expr * arg1    = *it1;
 | 
			
		||||
        expr * arg2    = *it2;
 | 
			
		||||
        TRACE("expr_bv_util", tout << "low1: " << low1 << " low2: " << low2 << "\n";
 | 
			
		||||
              ast_ll_pp(tout, m_manager, arg1); 
 | 
			
		||||
              ast_ll_pp(tout, m_manager, arg2););
 | 
			
		||||
              tout << mk_pp(arg1, m_manager) << "\n";
 | 
			
		||||
              tout << mk_pp(arg2, m_manager) << "\n";);
 | 
			
		||||
        unsigned sz1  = get_bv_size(arg1);
 | 
			
		||||
        unsigned sz2  = get_bv_size(arg2);
 | 
			
		||||
        SASSERT(low1 < sz1 && low2 < sz2);
 | 
			
		||||
        unsigned rsz1 = sz1 - low1;
 | 
			
		||||
        unsigned rsz2 = sz2 - low2;
 | 
			
		||||
        TRACE("expr_bv_util", tout << "rsz1: " << rsz1 << " rsz2: " << rsz2 << "\n";
 | 
			
		||||
              ast_ll_pp(tout, m_manager, arg1); ast_ll_pp(tout, m_manager, arg2););
 | 
			
		||||
 | 
			
		||||
              tout << mk_pp(arg1, m_manager) << "\n";
 | 
			
		||||
              tout << mk_pp(arg2, m_manager) << "\n";);
 | 
			
		||||
 | 
			
		||||
        if (rsz1 == rsz2) {
 | 
			
		||||
            mk_extract(sz1 - 1, low1, arg1, lhs);
 | 
			
		||||
| 
						 | 
				
			
			@ -826,9 +850,9 @@ void bv_simplifier_plugin::mk_eq_core(expr * arg1, expr * arg2, expr_ref & resul
 | 
			
		|||
        }        
 | 
			
		||||
        m_bsimp.mk_and(tmps.size(), tmps.c_ptr(), result);
 | 
			
		||||
        TRACE("mk_eq_bb", 
 | 
			
		||||
              ast_ll_pp(tout, m_manager, arg1);
 | 
			
		||||
              ast_ll_pp(tout, m_manager, arg2);
 | 
			
		||||
              ast_ll_pp(tout, m_manager, result););
 | 
			
		||||
              tout << mk_pp(arg1, m_manager) << "\n";
 | 
			
		||||
              tout << mk_pp(arg2, m_manager) << "\n";
 | 
			
		||||
              tout << mk_pp(result, m_manager) << "\n";);
 | 
			
		||||
        return;
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,6 +18,7 @@ Author:
 | 
			
		|||
#include"ast_pp.h"
 | 
			
		||||
#include"ast_util.h"
 | 
			
		||||
#include"ast_smt2_pp.h"
 | 
			
		||||
#include"ast_ll_pp.h"
 | 
			
		||||
 | 
			
		||||
poly_simplifier_plugin::poly_simplifier_plugin(symbol const & fname, ast_manager & m, decl_kind add, decl_kind mul, decl_kind uminus, decl_kind sub,
 | 
			
		||||
                                               decl_kind num):
 | 
			
		||||
| 
						 | 
				
			
			@ -173,7 +174,7 @@ void poly_simplifier_plugin::mk_monomial(unsigned num_args, expr * * args, expr_
 | 
			
		|||
        result = args[0];
 | 
			
		||||
        break;
 | 
			
		||||
    default:
 | 
			
		||||
        std::sort(args, args + num_args, monomial_element_lt_proc(*this));
 | 
			
		||||
        std::stable_sort(args, args + num_args, monomial_element_lt_proc(*this));
 | 
			
		||||
        result = mk_mul(num_args, args);
 | 
			
		||||
        SASSERT(wf_monomial(result));
 | 
			
		||||
        break;
 | 
			
		||||
| 
						 | 
				
			
			@ -284,6 +285,7 @@ bool poly_simplifier_plugin::merge_monomials(bool inv, expr * n1, expr * n2, exp
 | 
			
		|||
        else
 | 
			
		||||
            result = m_manager.mk_app(m_fid, m_MUL, mk_numeral(k1), b);
 | 
			
		||||
    }
 | 
			
		||||
    TRACE("merge_monomials", tout << mk_pp(n1, m_manager) << "\n" << mk_pp(n2, m_manager) << "\n" << mk_pp(result, m_manager) << "\n";);
 | 
			
		||||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -465,7 +467,9 @@ void poly_simplifier_plugin::mk_sum_of_monomials(expr_ref_vector & monomials, ex
 | 
			
		|||
        result = monomials.get(0);
 | 
			
		||||
        break;
 | 
			
		||||
    default: {
 | 
			
		||||
        std::sort(monomials.c_ptr(), monomials.c_ptr() + monomials.size(), monomial_lt_proc(*this));
 | 
			
		||||
        TRACE("mk_sum_sort", tout << "before\n"; for (unsigned i = 0; i < monomials.size(); i++) tout << mk_ll_pp(monomials.get(i), m_manager) << "\n";);
 | 
			
		||||
        std::stable_sort(monomials.c_ptr(), monomials.c_ptr() + monomials.size(), monomial_lt_proc(*this));
 | 
			
		||||
        TRACE("mk_sum_sort", tout << "after\n";  for (unsigned i = 0; i < monomials.size(); i++) tout << mk_ll_pp(monomials.get(i), m_manager) << "\n";);
 | 
			
		||||
        if (is_simple_sum_of_monomials(monomials)) {
 | 
			
		||||
            mk_sum_of_monomials_core(monomials.size(), monomials.c_ptr(), result);
 | 
			
		||||
            return;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -18,10 +18,6 @@ Revision History:
 | 
			
		|||
--*/
 | 
			
		||||
#include"matcher.h"
 | 
			
		||||
 | 
			
		||||
matcher::matcher(ast_manager & m):
 | 
			
		||||
    m_manager(m) {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool matcher::operator()(expr * e1, expr * e2, substitution & s) {
 | 
			
		||||
    reset();
 | 
			
		||||
    m_subst = &s;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -30,7 +30,6 @@ class matcher {
 | 
			
		|||
    typedef pair_hash<obj_ptr_hash<expr>, obj_ptr_hash<expr> > expr_pair_hash;
 | 
			
		||||
    typedef hashtable<expr_pair, expr_pair_hash, default_eq<expr_pair> > cache;
 | 
			
		||||
 | 
			
		||||
    ast_manager &         m_manager;
 | 
			
		||||
    substitution *        m_subst;
 | 
			
		||||
    // cache                 m_cache;
 | 
			
		||||
    svector<expr_pair>    m_todo;
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +37,7 @@ class matcher {
 | 
			
		|||
    void reset();
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    matcher(ast_manager & m);
 | 
			
		||||
    matcher() {}
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief Return true if e2 is an instance of e1.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -148,7 +148,7 @@ void substitution::apply(unsigned num_actual_offsets, unsigned const * deltas, e
 | 
			
		|||
                    expr * arg     = to_app(e)->get_arg(i);
 | 
			
		||||
                    expr * new_arg;
 | 
			
		||||
                    
 | 
			
		||||
                    m_apply_cache.find(expr_offset(arg, off), new_arg);
 | 
			
		||||
                    VERIFY(m_apply_cache.find(expr_offset(arg, off), new_arg));
 | 
			
		||||
                    new_args.push_back(new_arg);
 | 
			
		||||
                    if (arg != new_arg)
 | 
			
		||||
                        has_new_args = true;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -584,7 +584,7 @@ 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 << "\")" << std::endl;
 | 
			
		||||
            ctx.regular_stream() << "(:version \"" << Z3_MAJOR_VERSION << "." << Z3_MINOR_VERSION << "." << Z3_BUILD_NUMBER << "\")" << std::endl;
 | 
			
		||||
        }
 | 
			
		||||
        else if (opt == m_status) {
 | 
			
		||||
            ctx.regular_stream() << "(:status " << ctx.get_status() << ")" << std::endl;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -517,6 +517,9 @@ void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector<rational>& r
 | 
			
		|||
  int numps = s->get_num_parameters();
 | 
			
		||||
  rats.resize(numps-1);
 | 
			
		||||
  rats[0] = rational(1);
 | 
			
		||||
  ast conseq = arg(conc(proof),0);
 | 
			
		||||
  opr conseq_o = is_not(conseq) ? op(arg(conseq,0)) : op(conseq);
 | 
			
		||||
  bool conseq_neg = is_not(conseq) ? (conseq_o == Leq || conseq_o == Lt) : (conseq_o == Geq || conseq_o == Gt);
 | 
			
		||||
  for(int i = 2; i < numps; i++){
 | 
			
		||||
    rational r;
 | 
			
		||||
    bool ok = s->get_parameter(i).is_rational(r);
 | 
			
		||||
| 
						 | 
				
			
			@ -528,7 +531,8 @@ void iz3mgr::get_assign_bounds_coeffs(const ast &proof, std::vector<rational>& r
 | 
			
		|||
      opr o = is_not(con) ? op(arg(con,0)) : op(con);
 | 
			
		||||
      if(is_not(con) ? (o == Leq || o == Lt) : (o == Geq || o == Gt))
 | 
			
		||||
	r = -r;
 | 
			
		||||
      r = -r;
 | 
			
		||||
      if(conseq_neg)
 | 
			
		||||
	r = -r;
 | 
			
		||||
    }
 | 
			
		||||
    rats[i-1] = r;
 | 
			
		||||
  }
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -364,7 +364,7 @@ class iz3mgr  {
 | 
			
		|||
    return cook(to_func_decl(s)->get_parameters()[idx].get_ast());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  enum lemma_theory {ArithTheory,UnknownTheory};
 | 
			
		||||
  enum lemma_theory {ArithTheory,ArrayTheory,UnknownTheory};
 | 
			
		||||
 | 
			
		||||
  lemma_theory get_theory_lemma_theory(const ast &proof){
 | 
			
		||||
    symb s = sym(proof);
 | 
			
		||||
| 
						 | 
				
			
			@ -374,6 +374,8 @@ class iz3mgr  {
 | 
			
		|||
    std::string foo(p0.bare_str());
 | 
			
		||||
    if(foo == "arith")
 | 
			
		||||
      return ArithTheory;
 | 
			
		||||
    if(foo == "array")
 | 
			
		||||
      return ArrayTheory;
 | 
			
		||||
    return UnknownTheory;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -68,6 +68,10 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
     and yields a proof of false. */
 | 
			
		||||
  symb leq2eq;
 | 
			
		||||
 | 
			
		||||
  /* Equality to inequality. eq2leq(p, q) takes a proof p of x=y, and
 | 
			
		||||
     a proof q ~(x <= y) and and yields a proof of false. */
 | 
			
		||||
  symb eq2leq;
 | 
			
		||||
 | 
			
		||||
  /* Proof term cong(p,q) takes a proof p of x=y and a proof
 | 
			
		||||
     q of t != t<y/x> and returns a proof of false. */
 | 
			
		||||
  symb cong;
 | 
			
		||||
| 
						 | 
				
			
			@ -85,6 +89,9 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
     and q of ~Q and returns a proof of false. */
 | 
			
		||||
  symb modpon;
 | 
			
		||||
 | 
			
		||||
  /* This represents a lack of a proof */
 | 
			
		||||
  ast no_proof;
 | 
			
		||||
 | 
			
		||||
  // This is used to represent an infinitessimal value
 | 
			
		||||
  ast epsilon;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,13 +109,15 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast make_contra_node(const ast &pf, const std::vector<ast> &lits){
 | 
			
		||||
  ast make_contra_node(const ast &pf, const std::vector<ast> &lits, int pfok = -1){
 | 
			
		||||
    if(lits.size() == 0)
 | 
			
		||||
      return pf;
 | 
			
		||||
    std::vector<ast> reslits;
 | 
			
		||||
    reslits.push_back(make(contra,pf,mk_false()));
 | 
			
		||||
    for(unsigned i = 0; i < lits.size(); i++){
 | 
			
		||||
      ast bar = make(rotate_sum,lits[i],pf);
 | 
			
		||||
      ast bar;
 | 
			
		||||
      if(pfok & (1 << i)) bar = make(rotate_sum,lits[i],pf);
 | 
			
		||||
      else bar = no_proof;
 | 
			
		||||
      ast foo = make(contra,bar,lits[i]);
 | 
			
		||||
      reslits.push_back(foo);
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -129,6 +138,11 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      return pv->range_contained(r,rng) ? LitA : LitB;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool term_common(const ast &t){
 | 
			
		||||
    prover::range r = pv->ast_scope(t);
 | 
			
		||||
    return pv->ranges_intersect(r,rng) && !pv->range_contained(r,rng);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Make a resolution node with given pivot literal and premises.
 | 
			
		||||
      The conclusion of premise1 should contain the negation of the
 | 
			
		||||
      pivot literal, while the conclusion of premise2 should contain the
 | 
			
		||||
| 
						 | 
				
			
			@ -267,23 +281,58 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      if(!(f == pivot)){
 | 
			
		||||
	ast ph = get_placeholder(mk_not(arg(pivot1,1)));
 | 
			
		||||
	ast pf = arg(pivot1,0);
 | 
			
		||||
	ast thing = subst_term_and_simp(ph,pf,arg(f,0));
 | 
			
		||||
	ast thing = pf == no_proof ? no_proof : subst_term_and_simp(ph,pf,arg(f,0));
 | 
			
		||||
	ast newf = make(contra,thing,arg(f,1));
 | 
			
		||||
	res.push_back(newf);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  ast resolve_contra(const ast &pivot1, const ast &conj1,
 | 
			
		||||
  bool is_negative_equality(const ast &e){
 | 
			
		||||
    if(op(e) == Not){
 | 
			
		||||
      opr o = op(arg(e,0));
 | 
			
		||||
      return o == Equal || o == Iff;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int count_negative_equalities(const std::vector<ast> &resolvent){
 | 
			
		||||
    int res = 0;
 | 
			
		||||
    for(unsigned i = 0; i < resolvent.size(); i++)
 | 
			
		||||
      if(is_negative_equality(arg(resolvent[i],1)))
 | 
			
		||||
	res++;
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast resolve_contra_nf(const ast &pivot1, const ast &conj1,
 | 
			
		||||
		     const ast &pivot2, const ast &conj2){
 | 
			
		||||
    std::vector<ast> resolvent;
 | 
			
		||||
    collect_contra_resolvents(0,pivot1,pivot2,conj2,resolvent);
 | 
			
		||||
    collect_contra_resolvents(1,pivot2,pivot1,conj1,resolvent);
 | 
			
		||||
    if(count_negative_equalities(resolvent) > 1)
 | 
			
		||||
      throw proof_error();
 | 
			
		||||
    if(resolvent.size() == 1) // we have proved a contradiction
 | 
			
		||||
      return simplify(arg(resolvent[0],0)); // this is the proof -- get interpolant
 | 
			
		||||
    return make(And,resolvent);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast resolve_contra(const ast &pivot1, const ast &conj1,
 | 
			
		||||
			  const ast &pivot2, const ast &conj2){
 | 
			
		||||
#if 0
 | 
			
		||||
    int nargs = num_args(conj1);
 | 
			
		||||
    for(int i = 0; i < nargs; i++){
 | 
			
		||||
      ast foo = arg(conj1,i);
 | 
			
		||||
      if(!(foo == pivot1) && is_negative_equality(arg(foo,1)))
 | 
			
		||||
	return resolve_contra_nf(pivot2, conj2, pivot1, conj1);
 | 
			
		||||
    }
 | 
			
		||||
#endif
 | 
			
		||||
    if(arg(pivot1,0) != no_proof)
 | 
			
		||||
      return resolve_contra_nf(pivot1, conj1, pivot2, conj2);
 | 
			
		||||
    if(arg(pivot2,0) != no_proof)
 | 
			
		||||
      return resolve_contra_nf(pivot2, conj2, pivot1, conj1);
 | 
			
		||||
    return resolve_with_quantifier(pivot1, conj1, pivot2, conj2);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  bool is_contra_itp(const ast &pivot1, ast itp2, ast &pivot2){
 | 
			
		||||
    if(op(itp2) == And){
 | 
			
		||||
| 
						 | 
				
			
			@ -408,7 +457,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
  }
 | 
			
		||||
 | 
			
		||||
  /* This is where the real work happens. Here, we simplify the
 | 
			
		||||
     proof obtained by cut elimination, obtaining a interpolant. */
 | 
			
		||||
     proof obtained by cut elimination, obtaining an interpolant. */
 | 
			
		||||
 | 
			
		||||
  struct cannot_simplify {};
 | 
			
		||||
  hash_map<ast,ast> simplify_memo;
 | 
			
		||||
| 
						 | 
				
			
			@ -424,19 +473,23 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
    if(bar.second){
 | 
			
		||||
      int nargs = num_args(e);
 | 
			
		||||
      std::vector<ast> args(nargs);
 | 
			
		||||
      for(int i = 0; i < nargs; i++)
 | 
			
		||||
      bool placeholder_arg = false;
 | 
			
		||||
      for(int i = 0; i < nargs; i++){
 | 
			
		||||
	args[i] = simplify_rec(arg(e,i));
 | 
			
		||||
	placeholder_arg |= is_placeholder(args[i]);
 | 
			
		||||
      }
 | 
			
		||||
      try {
 | 
			
		||||
	opr f = op(e);
 | 
			
		||||
	if(f == Equal && args[0] == args[1]) res = mk_true();
 | 
			
		||||
	else if(f == And) res = my_and(args);
 | 
			
		||||
	else if(f == Or) res = my_or(args);
 | 
			
		||||
	else if(f == Idiv) res = mk_idiv(args[0],args[1]);
 | 
			
		||||
	else if(f == Uninterpreted){
 | 
			
		||||
	else if(f == Uninterpreted && !placeholder_arg){
 | 
			
		||||
	  symb g = sym(e);
 | 
			
		||||
	  if(g == rotate_sum) res = simplify_rotate(args);
 | 
			
		||||
	  else if(g == symm) res = simplify_symm(args);
 | 
			
		||||
	  else if(g == modpon) res = simplify_modpon(args);
 | 
			
		||||
	  else if(g == sum) res = simplify_sum(args);
 | 
			
		||||
#if 0
 | 
			
		||||
	  else if(g == cong) res = simplify_cong(args);
 | 
			
		||||
	  else if(g == modpon) res = simplify_modpon(args);
 | 
			
		||||
| 
						 | 
				
			
			@ -462,17 +515,26 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      symb g = sym(pf);
 | 
			
		||||
      if(g == sum) return simplify_rotate_sum(pl,pf);
 | 
			
		||||
      if(g == leq2eq) return simplify_rotate_leq2eq(pl,args[0],pf);
 | 
			
		||||
      if(g == eq2leq) return simplify_rotate_eq2leq(pl,args[0],pf);
 | 
			
		||||
      if(g == cong) return simplify_rotate_cong(pl,args[0],pf);
 | 
			
		||||
      if(g == modpon) return simplify_rotate_modpon(pl,args[0],pf);
 | 
			
		||||
      // if(g == symm) return simplify_rotate_symm(pl,args[0],pf);
 | 
			
		||||
    }
 | 
			
		||||
    throw cannot_simplify();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast simplify_sum(std::vector<ast> &args){
 | 
			
		||||
    ast cond = mk_true();
 | 
			
		||||
    ast ineq = args[0];
 | 
			
		||||
    if(!is_ineq(ineq)) throw cannot_simplify();
 | 
			
		||||
    sum_cond_ineq(ineq,cond,args[1],args[2]);
 | 
			
		||||
    return my_implies(cond,ineq);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast simplify_rotate_sum(const ast &pl, const ast &pf){
 | 
			
		||||
    ast cond = mk_true();
 | 
			
		||||
    ast ineq = make(Leq,make_int("0"),make_int("0"));
 | 
			
		||||
    rotate_sum_rec(pl,pf,cond,ineq);
 | 
			
		||||
    return ineq;
 | 
			
		||||
    return rotate_sum_rec(pl,pf,cond,ineq);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  void sum_cond_ineq(ast &ineq, ast &cond, const ast &coeff2, const ast &ineq2){
 | 
			
		||||
| 
						 | 
				
			
			@ -481,18 +543,26 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      sum_cond_ineq(ineq,cond,coeff2,arg(ineq2,1));
 | 
			
		||||
      cond = my_and(cond,arg(ineq2,0));
 | 
			
		||||
    }
 | 
			
		||||
    else if(o == Leq || o == Lt)
 | 
			
		||||
      ineq = sum_ineq(make_int("1"),ineq,coeff2,ineq2);
 | 
			
		||||
    else if(is_ineq(ineq2))
 | 
			
		||||
      linear_comb(ineq,coeff2,ineq2);
 | 
			
		||||
    else
 | 
			
		||||
      throw cannot_simplify();
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  bool is_ineq(const ast &ineq){
 | 
			
		||||
    opr o = op(ineq);
 | 
			
		||||
    if(o == Not) o = op(arg(ineq,0));
 | 
			
		||||
    return o == Leq || o == Lt || o == Geq || o == Gt;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  // divide both sides of inequality by a non-negative integer divisor
 | 
			
		||||
  ast idiv_ineq(const ast &ineq, const ast &divisor){
 | 
			
		||||
    return make(op(ineq),mk_idiv(arg(ineq,0),divisor),mk_idiv(arg(ineq,1),divisor));
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  ast rotate_sum_rec(const ast &pl, const ast &pf, ast &cond, ast &ineq){
 | 
			
		||||
    if(pf == pl)
 | 
			
		||||
      return my_implies(cond,simplify_ineq(ineq));
 | 
			
		||||
    if(op(pf) == Uninterpreted && sym(pf) == sum){
 | 
			
		||||
      if(arg(pf,2) == pl){
 | 
			
		||||
	sum_cond_ineq(ineq,cond,make_int("1"),arg(pf,0));
 | 
			
		||||
| 
						 | 
				
			
			@ -510,25 +580,57 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      ast equality = arg(neg_equality,0);
 | 
			
		||||
      ast x = arg(equality,0);
 | 
			
		||||
      ast y = arg(equality,1);
 | 
			
		||||
      ast xleqy = arg(pf,1);
 | 
			
		||||
      ast yleqx = arg(pf,2);
 | 
			
		||||
      ast xleqy = round_ineq(arg(pf,1));
 | 
			
		||||
      ast yleqx = round_ineq(arg(pf,2));
 | 
			
		||||
      ast itpeq;
 | 
			
		||||
      if(get_term_type(x) == LitA)
 | 
			
		||||
	itpeq = make(Equal,x,make(Plus,x,get_ineq_rhs(xleqy)));
 | 
			
		||||
	itpeq = make(Equal,x,z3_simplify(make(Plus,x,get_ineq_rhs(xleqy))));
 | 
			
		||||
      else if(get_term_type(y) == LitA)
 | 
			
		||||
	itpeq = make(Equal,make(Plus,y,get_ineq_rhs(yleqx)),y);
 | 
			
		||||
	itpeq = make(Equal,z3_simplify(make(Plus,y,get_ineq_rhs(yleqx))),y);
 | 
			
		||||
      else 
 | 
			
		||||
	throw cannot_simplify();
 | 
			
		||||
      ast cond = mk_true();
 | 
			
		||||
      ast ineq = make(Leq,make_int("0"),make_int("0"));
 | 
			
		||||
      sum_cond_ineq(ineq,cond,make_int("-1"),xleqy);
 | 
			
		||||
      sum_cond_ineq(ineq,cond,make_int("-1"),yleqx);
 | 
			
		||||
      cond = my_and(cond,ineq);
 | 
			
		||||
      cond = z3_simplify(my_and(cond,ineq));
 | 
			
		||||
      return my_implies(cond,itpeq);
 | 
			
		||||
    }
 | 
			
		||||
    throw cannot_simplify();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast round_ineq(const ast &ineq){
 | 
			
		||||
    if(!is_ineq(ineq))
 | 
			
		||||
      throw cannot_simplify();
 | 
			
		||||
    ast res = simplify_ineq(ineq);
 | 
			
		||||
    if(op(res) == Lt)
 | 
			
		||||
      res = make(Leq,arg(res,0),make(Sub,arg(res,1),make_int("1")));
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast simplify_rotate_eq2leq(const ast &pl, const ast &neg_equality, const ast &pf){
 | 
			
		||||
    if(pl == arg(pf,1)){
 | 
			
		||||
      ast cond = mk_true();
 | 
			
		||||
      ast equa = sep_cond(arg(pf,0),cond);
 | 
			
		||||
      if(op(equa) == Equal)
 | 
			
		||||
	return my_implies(cond,z3_simplify(make(Leq,make_int("0"),make(Sub,arg(equa,1),arg(equa,0)))));
 | 
			
		||||
      if(op(equa) == True)
 | 
			
		||||
	return my_implies(cond,z3_simplify(make(Leq,make_int("0"),make_int("0"))));
 | 
			
		||||
    }
 | 
			
		||||
    throw cannot_simplify();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast simplify_rotate_modpon(const ast &pl, const ast &neg_equality, const ast &pf){
 | 
			
		||||
    if(pl == arg(pf,2)){
 | 
			
		||||
      std::vector<ast> args; args.resize(3);
 | 
			
		||||
      args[0] = arg(pf,0);
 | 
			
		||||
      args[1] = arg(pf,1);
 | 
			
		||||
      args[2] = mk_true();
 | 
			
		||||
      return simplify_modpon(args);
 | 
			
		||||
    }    
 | 
			
		||||
    throw cannot_simplify();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast get_ineq_rhs(const ast &ineq2){
 | 
			
		||||
    opr o = op(ineq2);
 | 
			
		||||
    if(o == Implies)
 | 
			
		||||
| 
						 | 
				
			
			@ -564,8 +666,8 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      return mk_true();
 | 
			
		||||
    ast cond = mk_true();
 | 
			
		||||
    ast equa = sep_cond(args[0],cond);
 | 
			
		||||
    if(op(equa) == Equal)
 | 
			
		||||
      return my_implies(cond,make(Equal,arg(equa,1),arg(equa,0)));
 | 
			
		||||
    if(is_equivrel(equa))
 | 
			
		||||
      return my_implies(cond,make(op(equa),arg(equa,1),arg(equa,0)));
 | 
			
		||||
    throw cannot_simplify();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -575,12 +677,120 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      ast P = sep_cond(args[0],cond);
 | 
			
		||||
      ast notQ = sep_cond(args[2],cond);
 | 
			
		||||
      ast Q = mk_not(notQ);
 | 
			
		||||
      ast d = mk_not(delta(P,Q));
 | 
			
		||||
      ast d = op(notQ) == True ? P : op(P) == True ? notQ : mk_not(delta(P,Q));
 | 
			
		||||
      return my_implies(cond,d);
 | 
			
		||||
    }
 | 
			
		||||
    else {
 | 
			
		||||
      ast cond = mk_true();
 | 
			
		||||
      ast P = sep_cond(args[0],cond);
 | 
			
		||||
      ast PeqQ = sep_cond(args[1],cond);
 | 
			
		||||
      ast Q2 = sep_cond(args[2],cond);
 | 
			
		||||
      ast P1 = arg(PeqQ,0);
 | 
			
		||||
      ast Q1 = arg(PeqQ,1);
 | 
			
		||||
      if(op(P) == True){
 | 
			
		||||
	if(is_equivrel(P1) && is_equivrel(Q1)){ // special case of transitivity
 | 
			
		||||
	  if(arg(P1,0) == arg(Q1,0))
 | 
			
		||||
	    if(op(args[2]) == True)
 | 
			
		||||
	      return my_implies(cond,make(op(P1),arg(P1,1),arg(Q1,1)));
 | 
			
		||||
	}
 | 
			
		||||
	if(op(args[2]) == True)
 | 
			
		||||
	  throw cannot_simplify(); // return my_implies(cond,make(rewrite(P1,Q1)));
 | 
			
		||||
	ast A_rewrites = mk_true();
 | 
			
		||||
	ast foo = commute_rewrites(P1,Q1,mk_not(Q2),A_rewrites);
 | 
			
		||||
	return my_implies(cond,my_implies(my_implies(A_rewrites,foo),mk_false()));
 | 
			
		||||
      }
 | 
			
		||||
      else if(op(args[2]) == True){
 | 
			
		||||
	ast P2 = apply_common_rewrites(P,P,P1,cond);
 | 
			
		||||
	ast A_rewrites = mk_true();
 | 
			
		||||
	if(is_equivrel(P2)){
 | 
			
		||||
	  try {
 | 
			
		||||
	    ast foo = commute_rewrites(arg(P2,0),arg(P2,1),arg(Q1,1),A_rewrites);
 | 
			
		||||
	    ast P3 = make(op(P1),arg(P1,0),foo);
 | 
			
		||||
	    if(P3 == P2)
 | 
			
		||||
	      return my_implies(cond,Q1);
 | 
			
		||||
	    // return my_implies(cond,make(rewrite,my_implies(A_rewrites,P3),Q1));
 | 
			
		||||
	  }
 | 
			
		||||
	  catch(const rewrites_failed &){
 | 
			
		||||
	    std::cout << "foo!\n";
 | 
			
		||||
	  }
 | 
			
		||||
	}
 | 
			
		||||
	ast Q2 = apply_all_rewrites(P2,P1,Q1);
 | 
			
		||||
	return my_implies(cond,Q2);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    throw cannot_simplify();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool is_equivrel(const ast &p){
 | 
			
		||||
    opr o = op(p);
 | 
			
		||||
    return o == Equal || o == Iff;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  struct rewrites_failed{};
 | 
			
		||||
 | 
			
		||||
  /* Suppose p in Lang(B) and A |- p -> q and B |- q -> r. Return a z in Lang(B) such that
 | 
			
		||||
     B |- p -> z and A |- z -> q. Collect any side conditions in "rules". */
 | 
			
		||||
 | 
			
		||||
  ast commute_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){
 | 
			
		||||
    if(q == r)
 | 
			
		||||
      return p;
 | 
			
		||||
    if(p == q)
 | 
			
		||||
      return r;
 | 
			
		||||
    else {
 | 
			
		||||
      ast rew = make(Equal,q,r);
 | 
			
		||||
      if(get_term_type(rew) == LitB){
 | 
			
		||||
	apply_common_rewrites(p,p,q,rules); // A rewrites must be over comon vocab
 | 
			
		||||
	return r;
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    if(sym(p) != sym(q) || sym(q) != sym(r))
 | 
			
		||||
      throw rewrites_failed();
 | 
			
		||||
    int nargs = num_args(p);
 | 
			
		||||
    if(nargs != num_args(q) || nargs != num_args(r))
 | 
			
		||||
      throw rewrites_failed();
 | 
			
		||||
    std::vector<ast> args; args.resize(nargs);
 | 
			
		||||
    for(int i = 0; i < nargs; i++)
 | 
			
		||||
      args[i] = commute_rewrites(arg(p,i),arg(q,i),arg(r,i),rules);
 | 
			
		||||
    return clone(p,args);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast apply_common_rewrites(const ast &p, const ast &q, const ast &r, ast &rules){
 | 
			
		||||
    if(q == r)
 | 
			
		||||
      return p;
 | 
			
		||||
    ast rew = make(Equal,q,r);
 | 
			
		||||
    if(term_common(rew)){
 | 
			
		||||
      if(p != q)
 | 
			
		||||
	throw rewrites_failed();
 | 
			
		||||
      rules = my_and(rules,rew);
 | 
			
		||||
      return r;
 | 
			
		||||
    }
 | 
			
		||||
    if(sym(p) != sym(q) || sym(q) != sym(r))
 | 
			
		||||
      return p;
 | 
			
		||||
    int nargs = num_args(p);
 | 
			
		||||
    if(nargs != num_args(q) || nargs != num_args(r))
 | 
			
		||||
      return p;
 | 
			
		||||
    std::vector<ast> args; args.resize(nargs);
 | 
			
		||||
    for(int i = 0; i < nargs; i++)
 | 
			
		||||
      args[i] = apply_common_rewrites(arg(p,i),arg(q,i),arg(r,i),rules);
 | 
			
		||||
    return clone(p,args);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast apply_all_rewrites(const ast &p, const ast &q, const ast &r){
 | 
			
		||||
    if(q == r)
 | 
			
		||||
      return p;
 | 
			
		||||
    if(p == q)
 | 
			
		||||
      return r;
 | 
			
		||||
    if(sym(p) != sym(q) || sym(q) != sym(r))
 | 
			
		||||
      throw rewrites_failed();
 | 
			
		||||
    int nargs = num_args(p);
 | 
			
		||||
    if(nargs != num_args(q) || nargs != num_args(r))
 | 
			
		||||
      throw rewrites_failed();
 | 
			
		||||
    std::vector<ast> args; args.resize(nargs);
 | 
			
		||||
    for(int i = 0; i < nargs; i++)
 | 
			
		||||
      args[i] = apply_all_rewrites(arg(p,i),arg(q,i),arg(r,i));
 | 
			
		||||
    return clone(p,args);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast delta(const ast &x, const ast &y){
 | 
			
		||||
    if(op(x) != op(y) || (op(x) == Uninterpreted && sym(x) != sym(y)) || num_args(x) != num_args(y))
 | 
			
		||||
      return make(Equal,x,y);
 | 
			
		||||
| 
						 | 
				
			
			@ -617,6 +827,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
  ast triv_interp(const symb &rule, const std::vector<ast> &premises){
 | 
			
		||||
    std::vector<ast> ps; ps.resize(premises.size());
 | 
			
		||||
    std::vector<ast> conjs;
 | 
			
		||||
    int mask = 0;
 | 
			
		||||
    for(unsigned i = 0; i < ps.size(); i++){
 | 
			
		||||
      ast p = premises[i];
 | 
			
		||||
      switch(get_term_type(p)){
 | 
			
		||||
| 
						 | 
				
			
			@ -627,12 +838,14 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
	ps[i] = mk_true();
 | 
			
		||||
	break;
 | 
			
		||||
      default:
 | 
			
		||||
	ps[i] = get_placeholder(p);
 | 
			
		||||
	ps[i] = get_placeholder(p); // can only prove consequent!
 | 
			
		||||
	if(i == ps.size()-1)
 | 
			
		||||
	  mask |= (1 << conjs.size());
 | 
			
		||||
	conjs.push_back(p);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    ast ref = make(rule,ps);
 | 
			
		||||
    ast res = make_contra_node(ref,conjs);
 | 
			
		||||
    ast res = make_contra_node(ref,conjs,mask);
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -689,8 +902,30 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
 | 
			
		||||
  /** Make an axiom node. The conclusion must be an instance of an axiom. */
 | 
			
		||||
  virtual node make_axiom(const std::vector<ast> &conclusion){
 | 
			
		||||
    throw proof_error();
 | 
			
		||||
}
 | 
			
		||||
    prover::range frng = pv->range_full();
 | 
			
		||||
    int nargs = conclusion.size();
 | 
			
		||||
    std::vector<ast> largs(nargs);
 | 
			
		||||
    std::vector<ast> eqs;
 | 
			
		||||
    std::vector<ast> pfs;
 | 
			
		||||
    
 | 
			
		||||
    for(int i = 0; i < nargs; i++){
 | 
			
		||||
      ast argpf;
 | 
			
		||||
      ast lit = conclusion[i];
 | 
			
		||||
      largs[i] = localize_term(lit,frng,argpf);
 | 
			
		||||
      frng = pv->range_glb(frng,pv->ast_scope(largs[i]));
 | 
			
		||||
      if(largs[i] != lit){
 | 
			
		||||
	eqs.push_back(make_equiv(largs[i],lit));
 | 
			
		||||
	pfs.push_back(argpf);
 | 
			
		||||
      }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    int frame = pv->range_max(frng);
 | 
			
		||||
    ast itp = make_assumption(frame,largs);
 | 
			
		||||
    
 | 
			
		||||
    for(unsigned i = 0; i < eqs.size(); i++)
 | 
			
		||||
      itp = make_mp(eqs[i],itp,pfs[i]);
 | 
			
		||||
    return itp;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Make a Contra node. This rule takes a derivation of the form
 | 
			
		||||
     Gamma |- False and produces |- \/~Gamma. */
 | 
			
		||||
| 
						 | 
				
			
			@ -880,6 +1115,45 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
    return itp;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  int find_congruence_position(const ast &p, const ast &con){
 | 
			
		||||
      // find the argument position of x and y
 | 
			
		||||
    const ast &x = arg(p,0);
 | 
			
		||||
    const ast &y = arg(p,1);
 | 
			
		||||
    int nargs = num_args(arg(con,0));
 | 
			
		||||
    for(int i = 0; i < nargs; i++)
 | 
			
		||||
      if(x == arg(arg(con,0),i) && y == arg(arg(con,1),i))
 | 
			
		||||
	return i;
 | 
			
		||||
    throw proof_error();
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,...
 | 
			
		||||
      and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */
 | 
			
		||||
  
 | 
			
		||||
  node make_congruence(const std::vector<ast> &p, const ast &con, const std::vector<ast> &prems){
 | 
			
		||||
    if(p.size() == 0)
 | 
			
		||||
      throw proof_error();
 | 
			
		||||
    if(p.size() == 1)
 | 
			
		||||
      return make_congruence(p[0],con,prems[0]);
 | 
			
		||||
    ast thing = con;
 | 
			
		||||
    ast res = mk_true();
 | 
			
		||||
    for(unsigned i = 0; i < p.size(); i++){
 | 
			
		||||
      int pos = find_congruence_position(p[i],thing);
 | 
			
		||||
      ast next = subst_in_arg_pos(pos,arg(p[i],1),arg(thing,0));
 | 
			
		||||
      ast goal = make(op(thing),arg(thing,0),next);
 | 
			
		||||
      ast equa = make_congruence(p[i],goal,prems[i]);
 | 
			
		||||
      if(i == 0)
 | 
			
		||||
	res = equa;
 | 
			
		||||
      else {
 | 
			
		||||
	ast trace = make(op(con),arg(con,0),arg(thing,0));
 | 
			
		||||
	ast equiv = make(Iff,trace,make(op(trace),arg(trace,0),next));
 | 
			
		||||
	ast foo = make_congruence(goal,equiv,equa);
 | 
			
		||||
	res = make_mp(equiv,res,foo);
 | 
			
		||||
      }
 | 
			
		||||
      thing = make(op(thing),next,arg(thing,1));
 | 
			
		||||
    }
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  /* Interpolate a mixed congruence axiom. */
 | 
			
		||||
 | 
			
		||||
  virtual ast make_mixed_congruence(const ast &x, const ast &y, const ast &p, const ast &con, const ast &prem1){
 | 
			
		||||
| 
						 | 
				
			
			@ -1037,7 +1311,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
			     get_placeholder(mk_not(con)),
 | 
			
		||||
			     get_placeholder(xleqy),
 | 
			
		||||
			     get_placeholder(yleqx)),
 | 
			
		||||
			conjs);
 | 
			
		||||
			     conjs,1);
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
    return itp;
 | 
			
		||||
| 
						 | 
				
			
			@ -1054,6 +1328,7 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      itp =  mk_true();
 | 
			
		||||
      break;
 | 
			
		||||
    default: { // mixed equality
 | 
			
		||||
#if 0
 | 
			
		||||
      ast mid = get_placeholder(make(Equal,x,y));
 | 
			
		||||
      if(get_term_type(y) == LitA){
 | 
			
		||||
	std::swap(x,y);
 | 
			
		||||
| 
						 | 
				
			
			@ -1065,6 +1340,12 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      ast zleqmid = make(Leq,make_int("0"),mid);
 | 
			
		||||
      ast fark = make(contra,make_int("1"),mk_not(xleqy));
 | 
			
		||||
      itp = make(And,zleqmid,fark);
 | 
			
		||||
#endif
 | 
			
		||||
      std::vector<ast> conjs; conjs.resize(2);
 | 
			
		||||
      conjs[0] = make(Equal,x,y);
 | 
			
		||||
      conjs[1] = mk_not(xleqy);
 | 
			
		||||
      itp = make(eq2leq,get_placeholder(conjs[0]),get_placeholder(conjs[1]));
 | 
			
		||||
      itp = make_contra_node(itp,conjs);
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
    return itp;
 | 
			
		||||
| 
						 | 
				
			
			@ -1083,10 +1364,17 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
      itp =  mk_true();
 | 
			
		||||
      break;
 | 
			
		||||
    default: {
 | 
			
		||||
      std::vector<ast> conjs; conjs.resize(2);
 | 
			
		||||
      conjs[0] = tleqc;
 | 
			
		||||
      conjs[1] = mk_not(con);
 | 
			
		||||
      itp = make(sum,get_placeholder(conjs[0]),d,get_placeholder(conjs[1]));
 | 
			
		||||
      itp = make_contra_node(itp,conjs);
 | 
			
		||||
#if 0
 | 
			
		||||
      ast t = arg(tleqc,0);
 | 
			
		||||
      ast c = arg(tleqc,1);
 | 
			
		||||
      ast thing = make(contra,make_int("1"),mk_not(con));
 | 
			
		||||
      itp = make(And,make(Leq,make_int("0"),make(Idiv,get_placeholder(tleqc),d)),thing);
 | 
			
		||||
#endif
 | 
			
		||||
    }
 | 
			
		||||
    }
 | 
			
		||||
    std::vector<ast> conc; conc.push_back(con);
 | 
			
		||||
| 
						 | 
				
			
			@ -1096,6 +1384,130 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
  
 | 
			
		||||
  // create a fresh variable for localization
 | 
			
		||||
  ast fresh_localization_var(const ast &term, int frame){
 | 
			
		||||
    std::ostringstream s;
 | 
			
		||||
    s << "%" << (localization_vars.size());
 | 
			
		||||
    ast var = make_var(s.str().c_str(),get_type(term));
 | 
			
		||||
    pv->sym_range(sym(var)) = pv->range_full(); // make this variable global
 | 
			
		||||
    localization_vars.push_back(LocVar(var,term,frame));
 | 
			
		||||
    return var;
 | 
			
		||||
  }
 | 
			
		||||
  
 | 
			
		||||
  struct LocVar {                           // localization vars
 | 
			
		||||
    ast var;                                // a fresh variable
 | 
			
		||||
    ast term;                               // term it represents
 | 
			
		||||
    int frame;                              // frame in which it's defined
 | 
			
		||||
    LocVar(ast v, ast t, int f){var=v;term=t;frame=f;}
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  std::vector<LocVar> localization_vars;         // localization vars in order of creation
 | 
			
		||||
  hash_map<ast,ast> localization_map;            // maps terms to their localization vars
 | 
			
		||||
  hash_map<ast,ast> localization_pf_map;         // maps terms to proofs of their localizations
 | 
			
		||||
 | 
			
		||||
  /* "localize" a term e to a given frame range, creating new symbols to
 | 
			
		||||
     represent non-local subterms. This returns the localized version e_l,
 | 
			
		||||
     as well as a proof thet e_l = l. 
 | 
			
		||||
  */
 | 
			
		||||
 | 
			
		||||
  ast make_refl(const ast &e){
 | 
			
		||||
    return mk_true(); // TODO: is this right?
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
  ast make_equiv(const ast &x, const ast &y){
 | 
			
		||||
    if(get_type(x) == bool_type())
 | 
			
		||||
      return make(Iff,x,y);
 | 
			
		||||
    else
 | 
			
		||||
      return make(Equal,x,y);
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast localize_term(ast e, const prover::range &rng, ast &pf){
 | 
			
		||||
    ast orig_e = e;
 | 
			
		||||
    pf = make_refl(e);  // proof that e = e
 | 
			
		||||
 | 
			
		||||
    prover::range erng = pv->ast_scope(e);
 | 
			
		||||
    if(!(erng.lo > erng.hi) && pv->ranges_intersect(pv->ast_scope(e),rng)){
 | 
			
		||||
      return e; // this term occurs in range, so it's O.K.
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    hash_map<ast,ast>::iterator it = localization_map.find(e);
 | 
			
		||||
    if(it != localization_map.end()){
 | 
			
		||||
      pf = localization_pf_map[e];
 | 
			
		||||
      return it->second;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // if is is non-local, we must first localize the arguments to
 | 
			
		||||
    // the range of its function symbol
 | 
			
		||||
    
 | 
			
		||||
    int nargs = num_args(e);
 | 
			
		||||
    if(nargs > 0 /*  && (!is_local(e) || flo <= hi || fhi >= lo) */){
 | 
			
		||||
      prover::range frng = rng;
 | 
			
		||||
      if(op(e) == Uninterpreted){
 | 
			
		||||
	symb f = sym(e);
 | 
			
		||||
	prover::range srng = pv->sym_range(f);
 | 
			
		||||
	if(pv->ranges_intersect(srng,rng)) // localize to desired range if possible
 | 
			
		||||
	  frng = pv->range_glb(srng,rng);
 | 
			
		||||
      }
 | 
			
		||||
      std::vector<ast> largs(nargs);
 | 
			
		||||
      std::vector<ast> eqs;
 | 
			
		||||
      std::vector<ast> pfs;
 | 
			
		||||
      for(int i = 0; i < nargs; i++){
 | 
			
		||||
	ast argpf;
 | 
			
		||||
	largs[i] = localize_term(arg(e,i),frng,argpf);
 | 
			
		||||
	frng = pv->range_glb(frng,pv->ast_scope(largs[i]));
 | 
			
		||||
	if(largs[i] != arg(e,i)){
 | 
			
		||||
	  eqs.push_back(make_equiv(largs[i],arg(e,i)));
 | 
			
		||||
	  pfs.push_back(argpf);
 | 
			
		||||
	}
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      e = clone(e,largs);
 | 
			
		||||
      if(pfs.size())
 | 
			
		||||
	pf = make_congruence(eqs,make_equiv(e,orig_e),pfs);
 | 
			
		||||
      // assert(is_local(e));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    if(pv->ranges_intersect(pv->ast_scope(e),rng))
 | 
			
		||||
      return e; // this term occurs in range, so it's O.K.
 | 
			
		||||
 | 
			
		||||
    // choose a frame for the constraint that is close to range
 | 
			
		||||
    int frame = pv->range_near(pv->ast_scope(e),rng);
 | 
			
		||||
 | 
			
		||||
    ast new_var = fresh_localization_var(e,frame);
 | 
			
		||||
    localization_map[e] = new_var;
 | 
			
		||||
    std::vector<ast> foo; foo.push_back(make_equiv(new_var,e));
 | 
			
		||||
    ast bar = make_assumption(frame,foo);
 | 
			
		||||
    pf = make_transitivity(new_var,e,orig_e,bar,pf);
 | 
			
		||||
    localization_pf_map[orig_e] = pf;
 | 
			
		||||
    return new_var;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  node make_resolution(ast pivot, node premise1, node premise2) {
 | 
			
		||||
    std::vector<ast> lits;
 | 
			
		||||
    return make_resolution(pivot,lits,premise1,premise2);
 | 
			
		||||
  }  
 | 
			
		||||
 | 
			
		||||
  ast resolve_with_quantifier(const ast &pivot1, const ast &conj1,
 | 
			
		||||
			      const ast &pivot2, const ast &conj2){
 | 
			
		||||
   if(is_not(arg(pivot1,1)))
 | 
			
		||||
      return resolve_with_quantifier(pivot2,conj2,pivot1,conj1);
 | 
			
		||||
    ast eqpf;
 | 
			
		||||
    ast P = arg(pivot1,1);
 | 
			
		||||
    ast Ploc = localize_term(P, rng, eqpf);
 | 
			
		||||
    ast pPloc = make_hypothesis(Ploc);
 | 
			
		||||
    ast pP = make_mp(make(Iff,Ploc,P),pPloc,eqpf);
 | 
			
		||||
    ast rP = make_resolution(P,conj1,pP);
 | 
			
		||||
    ast nP = mk_not(P);
 | 
			
		||||
    ast nPloc = mk_not(Ploc);
 | 
			
		||||
    ast neqpf = make_congruence(make(Iff,Ploc,P),make(Iff,nPloc,nP),eqpf);
 | 
			
		||||
    ast npPloc = make_hypothesis(nPloc);
 | 
			
		||||
    ast npP = make_mp(make(Iff,nPloc,nP),npPloc,neqpf);
 | 
			
		||||
    ast nrP = make_resolution(nP,conj2,npP);
 | 
			
		||||
    ast res = make_resolution(Ploc,rP,nrP);
 | 
			
		||||
    return res;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  ast get_contra_coeff(const ast &f){
 | 
			
		||||
    ast c = arg(f,0);
 | 
			
		||||
    // if(!is_not(arg(f,1)))
 | 
			
		||||
| 
						 | 
				
			
			@ -1129,6 +1541,15 @@ class iz3proof_itp_impl : public iz3proof_itp {
 | 
			
		|||
    return l;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
  bool is_placeholder(const ast &e){
 | 
			
		||||
    if(op(e) == Uninterpreted){
 | 
			
		||||
      std::string name = string_of_symbol(sym(e));
 | 
			
		||||
      if(name.size() > 2 && name[0] == '@' and name[1] == 'p')
 | 
			
		||||
	return true;
 | 
			
		||||
    }
 | 
			
		||||
    return false;
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
  iz3proof_itp_impl(prover *p, const prover::range &r, bool w)
 | 
			
		||||
    : iz3proof_itp(*p)
 | 
			
		||||
| 
						 | 
				
			
			@ -1144,11 +1565,13 @@ public:
 | 
			
		|||
    sum = function("@sum",3,boolintbooldom,bool_type());
 | 
			
		||||
    rotate_sum = function("@rotsum",2,boolbooldom,bool_type());
 | 
			
		||||
    leq2eq = function("@leq2eq",3,boolboolbooldom,bool_type());
 | 
			
		||||
    eq2leq = function("@eq2leq",2,boolbooldom,bool_type());
 | 
			
		||||
    cong = function("@cong",3,boolintbooldom,bool_type());
 | 
			
		||||
    exmid = function("@exmid",3,boolboolbooldom,bool_type());
 | 
			
		||||
    symm = function("@symm",1,booldom,bool_type());
 | 
			
		||||
    epsilon = make_var("@eps",int_type());
 | 
			
		||||
    modpon = function("@mp",3,boolboolbooldom,bool_type());
 | 
			
		||||
    no_proof = make_var("@nop",bool_type());
 | 
			
		||||
  }
 | 
			
		||||
 | 
			
		||||
};
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -94,6 +94,11 @@ class iz3proof_itp : public iz3mgr {
 | 
			
		|||
  
 | 
			
		||||
  virtual node make_congruence(const ast &xi_eq_yi, const ast &con, const ast &prem1) = 0;
 | 
			
		||||
 | 
			
		||||
  /** Make a congruence node. This takes derivations of |- x_i1 = y_i1, |- x_i2 = y_i2,...
 | 
			
		||||
      and produces |- f(...x_i1...x_i2...) = f(...y_i1...y_i2...) */
 | 
			
		||||
 | 
			
		||||
  virtual node make_congruence(const std::vector<ast> &xi_eq_yi, const ast &con, const std::vector<ast> &prems) = 0;
 | 
			
		||||
 | 
			
		||||
  /** Make a modus-ponens node. This takes derivations of |- x
 | 
			
		||||
      and |- x = y and produces |- y */
 | 
			
		||||
  
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -895,7 +895,7 @@ public:
 | 
			
		|||
      my_cons.push_back(mk_not(arg(con,i)));
 | 
			
		||||
      my_coeffs.push_back(farkas_coeffs[i]);
 | 
			
		||||
    }
 | 
			
		||||
    ast farkas_con = normalize_inequality(sum_inequalities(farkas_coeffs,my_cons));
 | 
			
		||||
    ast farkas_con = normalize_inequality(sum_inequalities(my_coeffs,my_cons));
 | 
			
		||||
    my_cons.push_back(mk_not(farkas_con));
 | 
			
		||||
    my_coeffs.push_back(make_int("1"));
 | 
			
		||||
    std::vector<Iproof::node> my_hyps;
 | 
			
		||||
| 
						 | 
				
			
			@ -976,15 +976,10 @@ public:
 | 
			
		|||
	break;
 | 
			
		||||
      }
 | 
			
		||||
      case PR_MONOTONICITY: {
 | 
			
		||||
	// assume the premise is x = y
 | 
			
		||||
	ast x = arg(conc(prem(proof,0)),0);
 | 
			
		||||
	ast y = arg(conc(prem(proof,0)),1);
 | 
			
		||||
#if 0
 | 
			
		||||
	AstSet &hyps = get_hyps(proof);
 | 
			
		||||
	std::vector<ast> hyps_vec; hyps_vec.resize(hyps.size());
 | 
			
		||||
	std::copy(hyps.begin(),hyps.end(),hyps_vec.begin());
 | 
			
		||||
#endif
 | 
			
		||||
	res = iproof->make_congruence(conc(prem(proof,0)),con,args[0]);
 | 
			
		||||
	std::vector<ast> eqs; eqs.resize(args.size());
 | 
			
		||||
	for(unsigned i = 0; i < args.size(); i++)
 | 
			
		||||
	  eqs[i] = conc(prem(proof,i));
 | 
			
		||||
	res = iproof->make_congruence(eqs,con,args);
 | 
			
		||||
	break;
 | 
			
		||||
      }
 | 
			
		||||
      case PR_REFLEXIVITY: {
 | 
			
		||||
| 
						 | 
				
			
			@ -1050,6 +1045,9 @@ public:
 | 
			
		|||
	    throw unsupported();
 | 
			
		||||
	  }
 | 
			
		||||
	  break;
 | 
			
		||||
	case ArrayTheory: // nothing fancy for this
 | 
			
		||||
	  res = iproof->make_axiom(lits);
 | 
			
		||||
	  break;
 | 
			
		||||
	default:
 | 
			
		||||
	  throw unsupported();
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ public:
 | 
			
		|||
};
 | 
			
		||||
 | 
			
		||||
//#define IZ3_TRANSLATE_DIRECT2
 | 
			
		||||
#ifndef _FOCI2
 | 
			
		||||
#ifdef _FOCI2
 | 
			
		||||
#define IZ3_TRANSLATE_DIRECT
 | 
			
		||||
#else
 | 
			
		||||
#define IZ3_TRANSLATE_FULL
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -123,9 +123,9 @@ class heap_trie {
 | 
			
		|||
        }
 | 
			
		||||
        
 | 
			
		||||
        // push nodes whose keys are <= key into vector.
 | 
			
		||||
        void find_le(Key key, ptr_vector<node>& nodes) {
 | 
			
		||||
        void find_le(KeyLE& le, Key key, ptr_vector<node>& nodes) {
 | 
			
		||||
            for (unsigned i = 0; i < m_nodes.size(); ++i) {
 | 
			
		||||
                if (KeyLE::le(m_nodes[i].first, key)) {
 | 
			
		||||
                if (le.le(m_nodes[i].first, key)) {
 | 
			
		||||
                    node* n = m_nodes[i].second;
 | 
			
		||||
                    if (n->ref_count() > 0){
 | 
			
		||||
                        nodes.push_back(n);
 | 
			
		||||
| 
						 | 
				
			
			@ -179,6 +179,7 @@ class heap_trie {
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    small_object_allocator m_alloc;
 | 
			
		||||
    KeyLE&   m_le;
 | 
			
		||||
    unsigned m_num_keys;
 | 
			
		||||
    unsigned_vector m_keys;
 | 
			
		||||
    unsigned m_do_reshuffle;
 | 
			
		||||
| 
						 | 
				
			
			@ -189,8 +190,9 @@ class heap_trie {
 | 
			
		|||
 | 
			
		||||
public:
 | 
			
		||||
 | 
			
		||||
    heap_trie():     
 | 
			
		||||
    heap_trie(KeyLE& le):    
 | 
			
		||||
        m_alloc("heap_trie"),
 | 
			
		||||
        m_le(le),
 | 
			
		||||
        m_num_keys(0),
 | 
			
		||||
        m_do_reshuffle(4),
 | 
			
		||||
        m_root(0),
 | 
			
		||||
| 
						 | 
				
			
			@ -255,7 +257,7 @@ public:
 | 
			
		|||
        for (unsigned i = 0; i < num_keys(); ++i) {
 | 
			
		||||
            for (unsigned j = 0; j < todo[index].size(); ++j) {
 | 
			
		||||
                ++m_stats.m_num_find_le_nodes;
 | 
			
		||||
                to_trie(todo[index][j])->find_le(get_key(keys, i), todo[!index]);
 | 
			
		||||
                to_trie(todo[index][j])->find_le(m_le, get_key(keys, i), todo[!index]);
 | 
			
		||||
            }
 | 
			
		||||
            todo[index].reset();
 | 
			
		||||
            index = !index;
 | 
			
		||||
| 
						 | 
				
			
			@ -577,7 +579,7 @@ private:
 | 
			
		|||
                               verbose_stream() << " ";
 | 
			
		||||
                           }
 | 
			
		||||
                           verbose_stream() << nodes[i].first << " <=? " << key << " rc:" << m->ref_count() << "\n";);
 | 
			
		||||
                if (m->ref_count() > 0 && KeyLE::le(nodes[i].first, key) && find_le(m, index+1, keys, check)) {
 | 
			
		||||
                if (m->ref_count() > 0 && m_le.le(nodes[i].first, key) && find_le(m, index+1, keys, check)) {
 | 
			
		||||
                    if (i > 0) {
 | 
			
		||||
                        std::swap(nodes[i], nodes[0]);
 | 
			
		||||
                    }
 | 
			
		||||
| 
						 | 
				
			
			@ -58,14 +58,13 @@ public:
 | 
			
		|||
        m_table.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool find(offset_t idx, values const& vs, offset_t& found_idx) {
 | 
			
		||||
    bool find(offset_t idx, values const& vs) {
 | 
			
		||||
        // display_profile(idx, std::cout);
 | 
			
		||||
        int_table::iterator it = m_table.begin(), end = m_table.end();
 | 
			
		||||
        for (; it != end; ++it) {
 | 
			
		||||
            offset_t offs(*it);
 | 
			
		||||
            ++m_stats.m_num_comparisons;
 | 
			
		||||
            if (*it != static_cast<int>(idx.m_offset) && hb.is_subsumed(idx, offs)) {
 | 
			
		||||
                found_idx = offs;
 | 
			
		||||
                ++m_stats.m_num_hit;
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
| 
						 | 
				
			
			@ -163,20 +162,21 @@ private:
 | 
			
		|||
 | 
			
		||||
class hilbert_basis::value_index2 {
 | 
			
		||||
    struct key_le {
 | 
			
		||||
        static bool le(numeral const& n1, numeral const& n2) {
 | 
			
		||||
            return hilbert_basis::is_abs_geq(n2, n1);
 | 
			
		||||
        hilbert_basis& hb;
 | 
			
		||||
        key_le(hilbert_basis& hb): hb(hb) {}
 | 
			
		||||
        bool le(numeral const& n1, numeral const& n2) const {
 | 
			
		||||
            return hb.is_abs_geq(n2, n1);
 | 
			
		||||
        }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    typedef heap_trie<numeral, key_le, numeral::hash_proc, unsigned> ht;
 | 
			
		||||
 | 
			
		||||
    struct checker : public ht::check_value {
 | 
			
		||||
        hilbert_basis* hb;
 | 
			
		||||
        offset_t  m_value;
 | 
			
		||||
        offset_t* m_found;
 | 
			
		||||
        checker(): hb(0), m_found(0) {}
 | 
			
		||||
        checker(): hb(0) {}
 | 
			
		||||
        virtual bool operator()(unsigned const& v) {            
 | 
			
		||||
            if (m_value.m_offset != v && hb->is_subsumed(m_value, offset_t(v))) {
 | 
			
		||||
                *m_found = offset_t(v);
 | 
			
		||||
            if (m_value.m_offset != v) { //  && hb->is_subsumed(m_value, offset_t(v))) {
 | 
			
		||||
                return true;
 | 
			
		||||
            }
 | 
			
		||||
            else {
 | 
			
		||||
| 
						 | 
				
			
			@ -185,23 +185,25 @@ class hilbert_basis::value_index2 {
 | 
			
		|||
        }
 | 
			
		||||
    };
 | 
			
		||||
    hilbert_basis&               hb;
 | 
			
		||||
    key_le                       m_le;
 | 
			
		||||
    ht                           m_trie;
 | 
			
		||||
    vector<unsigned>             m_found;
 | 
			
		||||
    bool                         m_init;
 | 
			
		||||
    checker                      m_checker;
 | 
			
		||||
    vector<numeral>              m_keys;
 | 
			
		||||
    unsigned                     m_offset;
 | 
			
		||||
 | 
			
		||||
    numeral const* get_keys(values const& vs) {
 | 
			
		||||
        return vs()-1;
 | 
			
		||||
        return vs()-m_offset;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    value_index2(hilbert_basis& hb): hb(hb), m_init(false) {
 | 
			
		||||
    value_index2(hilbert_basis& hb): 
 | 
			
		||||
        hb(hb), 
 | 
			
		||||
        m_le(hb),
 | 
			
		||||
        m_trie(m_le),
 | 
			
		||||
        m_offset(1) {
 | 
			
		||||
        m_checker.hb = &hb;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void insert(offset_t idx, values const& vs) {
 | 
			
		||||
        init();
 | 
			
		||||
        m_trie.insert(get_keys(vs), idx.m_offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -209,15 +211,13 @@ public:
 | 
			
		|||
        m_trie.remove(get_keys(vs));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void reset() {
 | 
			
		||||
        m_trie.reset(hb.get_num_vars()+1);
 | 
			
		||||
        m_keys.resize(hb.get_num_vars()+1);
 | 
			
		||||
    void reset(unsigned offset) {
 | 
			
		||||
        m_offset = offset;
 | 
			
		||||
        m_trie.reset(hb.get_num_vars()+m_offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool find(offset_t idx, values const& vs, offset_t& found_idx) {
 | 
			
		||||
        init();
 | 
			
		||||
    bool find(offset_t idx, values const& vs) {
 | 
			
		||||
        m_checker.m_value = idx;
 | 
			
		||||
        m_checker.m_found = &found_idx;
 | 
			
		||||
        return m_trie.find_le(get_keys(vs), m_checker);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -236,14 +236,6 @@ public:
 | 
			
		|||
    void display(std::ostream& out) const {
 | 
			
		||||
        // m_trie.display(out);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    void init() {
 | 
			
		||||
        if (!m_init) {
 | 
			
		||||
            reset();
 | 
			
		||||
            m_init = true;
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -254,6 +246,7 @@ class hilbert_basis::index {
 | 
			
		|||
 | 
			
		||||
    // typedef value_index1 value_index;
 | 
			
		||||
    typedef value_index2 value_index;
 | 
			
		||||
    // typedef value_index3 value_index;
 | 
			
		||||
 | 
			
		||||
    struct stats {
 | 
			
		||||
        unsigned m_num_find;
 | 
			
		||||
| 
						 | 
				
			
			@ -271,9 +264,10 @@ class hilbert_basis::index {
 | 
			
		|||
    value_index      m_pos;
 | 
			
		||||
    value_index      m_zero;
 | 
			
		||||
    stats            m_stats;
 | 
			
		||||
    unsigned         m_num_ineqs;
 | 
			
		||||
 | 
			
		||||
public:
 | 
			
		||||
    index(hilbert_basis& hb): hb(hb), m_pos(hb), m_zero(hb) {}
 | 
			
		||||
    index(hilbert_basis& hb): hb(hb), m_pos(hb), m_zero(hb), m_num_ineqs(0) {}
 | 
			
		||||
    
 | 
			
		||||
    void insert(offset_t idx, values const& vs) {
 | 
			
		||||
        ++m_stats.m_num_insert;
 | 
			
		||||
| 
						 | 
				
			
			@ -287,6 +281,7 @@ public:
 | 
			
		|||
            value_index* map = 0;
 | 
			
		||||
            if (!m_neg.find(vs.weight(), map)) {
 | 
			
		||||
                map = alloc(value_index, hb);
 | 
			
		||||
                map->reset(m_num_ineqs);
 | 
			
		||||
                m_neg.insert(vs.weight(), map);
 | 
			
		||||
            }
 | 
			
		||||
            map->insert(idx, vs);
 | 
			
		||||
| 
						 | 
				
			
			@ -305,29 +300,30 @@ public:
 | 
			
		|||
        }        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    bool find(offset_t idx, values const& vs, offset_t& found_idx) {
 | 
			
		||||
    bool find(offset_t idx, values const& vs) {
 | 
			
		||||
        ++m_stats.m_num_find;
 | 
			
		||||
        if (vs.weight().is_pos()) {
 | 
			
		||||
            return m_pos.find(idx,  vs, found_idx);
 | 
			
		||||
            return m_pos.find(idx,  vs);
 | 
			
		||||
        }
 | 
			
		||||
        else if (vs.weight().is_zero()) {
 | 
			
		||||
            return m_zero.find(idx, vs, found_idx);
 | 
			
		||||
            return m_zero.find(idx, vs);
 | 
			
		||||
        }
 | 
			
		||||
        else {
 | 
			
		||||
            value_index* map;
 | 
			
		||||
            return
 | 
			
		||||
                m_neg.find(vs.weight(), map) && 
 | 
			
		||||
                map->find(idx, vs, found_idx);
 | 
			
		||||
                map->find(idx, vs);
 | 
			
		||||
        }        
 | 
			
		||||
    }    
 | 
			
		||||
 | 
			
		||||
    void reset() {
 | 
			
		||||
    void reset(unsigned num_ineqs) {
 | 
			
		||||
        value_map::iterator it = m_neg.begin(), end = m_neg.end();
 | 
			
		||||
        for (; it != end; ++it) {
 | 
			
		||||
            it->m_value->reset();
 | 
			
		||||
            dealloc(it->m_value);
 | 
			
		||||
        }
 | 
			
		||||
        m_pos.reset();
 | 
			
		||||
        m_zero.reset();
 | 
			
		||||
        m_pos.reset(num_ineqs);
 | 
			
		||||
        m_zero.reset(num_ineqs);
 | 
			
		||||
        m_num_ineqs = num_ineqs;
 | 
			
		||||
        m_neg.reset();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -678,15 +674,25 @@ bool hilbert_basis::is_invalid_offset(offset_t offs) {
 | 
			
		|||
 | 
			
		||||
void hilbert_basis::reset() {
 | 
			
		||||
    m_ineqs.reset();
 | 
			
		||||
    m_basis.reset();
 | 
			
		||||
    m_iseq.reset();
 | 
			
		||||
    m_store.reset();
 | 
			
		||||
    m_basis.reset();
 | 
			
		||||
    m_free_list.reset();
 | 
			
		||||
    m_active.reset();
 | 
			
		||||
    m_passive->reset();
 | 
			
		||||
    m_passive2->reset();
 | 
			
		||||
    m_sos.reset();
 | 
			
		||||
    m_zero.reset();
 | 
			
		||||
    m_index->reset();
 | 
			
		||||
    m_cancel = false;
 | 
			
		||||
    m_active.reset();
 | 
			
		||||
    if (m_passive) {
 | 
			
		||||
        m_passive->reset();
 | 
			
		||||
    }
 | 
			
		||||
    if (m_passive2) {
 | 
			
		||||
        m_passive2->reset();
 | 
			
		||||
    }
 | 
			
		||||
    if (m_index) {
 | 
			
		||||
        m_index->reset(1);
 | 
			
		||||
    }
 | 
			
		||||
    m_ints.reset();
 | 
			
		||||
    m_current_ineq = 0;
 | 
			
		||||
    
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::collect_statistics(statistics& st) const {
 | 
			
		||||
| 
						 | 
				
			
			@ -702,42 +708,46 @@ void hilbert_basis::reset_statistics() {
 | 
			
		|||
    m_index->reset_statistics();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::add_ge(num_vector const& v, numeral const& b) {
 | 
			
		||||
void hilbert_basis::add_ge(rational_vector const& v, rational const& b) {
 | 
			
		||||
    SASSERT(m_ineqs.empty() || v.size() + 1 == m_ineqs.back().size());
 | 
			
		||||
    num_vector w;
 | 
			
		||||
    w.push_back(-b);
 | 
			
		||||
    w.append(v);
 | 
			
		||||
    w.push_back(to_numeral(-b));
 | 
			
		||||
    for (unsigned i = 0; i < v.size(); ++i) {
 | 
			
		||||
        w.push_back(to_numeral(v[i]));
 | 
			
		||||
    }
 | 
			
		||||
    m_ineqs.push_back(w);
 | 
			
		||||
    m_iseq.push_back(false);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::add_le(num_vector const& v, numeral const& b) {
 | 
			
		||||
    num_vector w(v);
 | 
			
		||||
void hilbert_basis::add_le(rational_vector const& v, rational const& b) {
 | 
			
		||||
    rational_vector w(v);
 | 
			
		||||
    for (unsigned i = 0; i < w.size(); ++i) {
 | 
			
		||||
        w[i].neg();
 | 
			
		||||
    }
 | 
			
		||||
    add_ge(w, -b);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::add_eq(num_vector const& v, numeral const& b) {
 | 
			
		||||
void hilbert_basis::add_eq(rational_vector const& v, rational const& b) {
 | 
			
		||||
    SASSERT(m_ineqs.empty() || v.size() + 1 == m_ineqs.back().size());
 | 
			
		||||
    num_vector w;
 | 
			
		||||
    w.push_back(-b);
 | 
			
		||||
    w.append(v);
 | 
			
		||||
    w.push_back(to_numeral(-b));
 | 
			
		||||
    for (unsigned i = 0; i < v.size(); ++i) {
 | 
			
		||||
        w.push_back(to_numeral(v[i]));
 | 
			
		||||
    }
 | 
			
		||||
    m_ineqs.push_back(w);
 | 
			
		||||
    m_iseq.push_back(true);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::add_ge(num_vector const& v) {
 | 
			
		||||
    add_ge(v, numeral(0));
 | 
			
		||||
void hilbert_basis::add_ge(rational_vector const& v) {
 | 
			
		||||
    add_ge(v, rational(0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::add_le(num_vector const& v) {
 | 
			
		||||
    add_le(v, numeral(0));
 | 
			
		||||
void hilbert_basis::add_le(rational_vector const& v) {
 | 
			
		||||
    add_le(v, rational(0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::add_eq(num_vector const& v) {
 | 
			
		||||
    add_eq(v, numeral(0));
 | 
			
		||||
void hilbert_basis::add_eq(rational_vector const& v) {
 | 
			
		||||
    add_eq(v, rational(0));
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::set_is_int(unsigned var_index) {
 | 
			
		||||
| 
						 | 
				
			
			@ -799,7 +809,7 @@ lbool hilbert_basis::saturate() {
 | 
			
		|||
        stopwatch sw;
 | 
			
		||||
        sw.start();
 | 
			
		||||
        lbool r = saturate(m_ineqs[m_current_ineq], m_iseq[m_current_ineq]);
 | 
			
		||||
        IF_VERBOSE(1,  
 | 
			
		||||
        IF_VERBOSE(3,  
 | 
			
		||||
                   { statistics st; 
 | 
			
		||||
                       collect_statistics(st); 
 | 
			
		||||
                       st.display(verbose_stream()); 
 | 
			
		||||
| 
						 | 
				
			
			@ -823,7 +833,7 @@ lbool hilbert_basis::saturate_orig(num_vector const& ineq, bool is_eq) {
 | 
			
		|||
    m_active.reset();
 | 
			
		||||
    m_passive->reset();
 | 
			
		||||
    m_zero.reset();
 | 
			
		||||
    m_index->reset();
 | 
			
		||||
    m_index->reset(m_current_ineq+1);
 | 
			
		||||
    int_table support;
 | 
			
		||||
    TRACE("hilbert_basis", display_ineq(tout, ineq, is_eq););
 | 
			
		||||
    iterator it = begin();
 | 
			
		||||
| 
						 | 
				
			
			@ -895,7 +905,7 @@ bool hilbert_basis::vector_lt(offset_t idx1, offset_t idx2) const {
 | 
			
		|||
 | 
			
		||||
lbool hilbert_basis::saturate(num_vector const& ineq, bool is_eq) {
 | 
			
		||||
    m_zero.reset();
 | 
			
		||||
    m_index->reset();
 | 
			
		||||
    m_index->reset(m_current_ineq+1);
 | 
			
		||||
    m_passive2->reset();
 | 
			
		||||
    m_sos.reset();
 | 
			
		||||
    TRACE("hilbert_basis", display_ineq(tout, ineq, is_eq););
 | 
			
		||||
| 
						 | 
				
			
			@ -974,19 +984,21 @@ lbool hilbert_basis::saturate(num_vector const& ineq, bool is_eq) {
 | 
			
		|||
    return m_basis.empty()?l_false:l_true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::get_basis_solution(unsigned i, num_vector& v, bool& is_initial) {
 | 
			
		||||
void hilbert_basis::get_basis_solution(unsigned i, rational_vector& v, bool& is_initial) {
 | 
			
		||||
    offset_t offs = m_basis[i];
 | 
			
		||||
    v.reset();
 | 
			
		||||
    for (unsigned i = 1; i < get_num_vars(); ++i) {
 | 
			
		||||
        v.push_back(vec(offs)[i]);
 | 
			
		||||
        v.push_back(to_rational(vec(offs)[i]));
 | 
			
		||||
    }
 | 
			
		||||
    is_initial = !vec(offs)[0].is_zero();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void hilbert_basis::get_ge(unsigned i, num_vector& v, numeral& b, bool& is_eq) {
 | 
			
		||||
void hilbert_basis::get_ge(unsigned i, rational_vector& v, rational& b, bool& is_eq) {
 | 
			
		||||
    v.reset();
 | 
			
		||||
    v.append(m_ineqs[i].size() - 1, m_ineqs[i].c_ptr() + 1);
 | 
			
		||||
    b = -m_ineqs[i][0];
 | 
			
		||||
    for (unsigned j = 1; j < m_ineqs[i].size(); ++j) {
 | 
			
		||||
        v.push_back(to_rational(m_ineqs[i][j]));
 | 
			
		||||
    }
 | 
			
		||||
    b = to_rational(-m_ineqs[i][0]);
 | 
			
		||||
    is_eq = m_iseq[i];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -996,11 +1008,9 @@ void hilbert_basis::select_inequality() {
 | 
			
		|||
    unsigned best = m_current_ineq;
 | 
			
		||||
    unsigned non_zeros = get_num_nonzeros(m_ineqs[best]);
 | 
			
		||||
    unsigned prod      = get_ineq_product(m_ineqs[best]);
 | 
			
		||||
    //numeral  diff      = get_ineq_diff(m_ineqs[best]);
 | 
			
		||||
    for (unsigned j = best+1; prod != 0 && j < m_ineqs.size(); ++j) {
 | 
			
		||||
        unsigned non_zeros2 = get_num_nonzeros(m_ineqs[j]);
 | 
			
		||||
        unsigned prod2 = get_ineq_product(m_ineqs[j]);
 | 
			
		||||
        //numeral diff2  = get_ineq_diff(m_ineqs[j]);
 | 
			
		||||
        if (prod2 == 0) {
 | 
			
		||||
            prod = prod2;
 | 
			
		||||
            non_zeros = non_zeros2;
 | 
			
		||||
| 
						 | 
				
			
			@ -1009,7 +1019,6 @@ void hilbert_basis::select_inequality() {
 | 
			
		|||
        }
 | 
			
		||||
        if (non_zeros2 < non_zeros || (non_zeros2 == non_zeros && prod2 < prod)) {
 | 
			
		||||
            prod = prod2;
 | 
			
		||||
            //  diff = diff2;
 | 
			
		||||
            non_zeros = non_zeros2;
 | 
			
		||||
            best = j;
 | 
			
		||||
        }
 | 
			
		||||
| 
						 | 
				
			
			@ -1121,8 +1130,7 @@ bool hilbert_basis::add_goal(offset_t idx) {
 | 
			
		|||
 | 
			
		||||
bool hilbert_basis::is_subsumed(offset_t idx)  {
 | 
			
		||||
 | 
			
		||||
    offset_t found_idx;
 | 
			
		||||
    if (m_index->find(idx, vec(idx), found_idx)) {        
 | 
			
		||||
    if (m_index->find(idx, vec(idx))) {        
 | 
			
		||||
        ++m_stats.m_num_subsumptions;
 | 
			
		||||
        return true;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -1316,7 +1324,7 @@ bool hilbert_basis::is_geq(values const& v, values const& w) const {
 | 
			
		|||
    return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
bool hilbert_basis::is_abs_geq(numeral const& v, numeral const& w) {
 | 
			
		||||
bool hilbert_basis::is_abs_geq(numeral const& v, numeral const& w) const {
 | 
			
		||||
    if (w.is_neg()) {
 | 
			
		||||
        return v <= w;
 | 
			
		||||
    }
 | 
			
		||||
| 
						 | 
				
			
			@ -18,6 +18,11 @@ Author:
 | 
			
		|||
 | 
			
		||||
Revision History:
 | 
			
		||||
 | 
			
		||||
    Hilbert basis can be templatized 
 | 
			
		||||
    based on traits that define numeral:
 | 
			
		||||
    as rational, mpz, checked_int64 
 | 
			
		||||
    (checked or unchecked).
 | 
			
		||||
 | 
			
		||||
--*/
 | 
			
		||||
 | 
			
		||||
#ifndef _HILBERT_BASIS_H_
 | 
			
		||||
| 
						 | 
				
			
			@ -26,14 +31,28 @@ Revision History:
 | 
			
		|||
#include "rational.h"
 | 
			
		||||
#include "lbool.h"
 | 
			
		||||
#include "statistics.h"
 | 
			
		||||
#include "checked_int64.h"
 | 
			
		||||
 | 
			
		||||
typedef vector<rational> rational_vector;
 | 
			
		||||
 | 
			
		||||
class hilbert_basis {
 | 
			
		||||
public:
 | 
			
		||||
    typedef rational numeral;
 | 
			
		||||
 | 
			
		||||
    static const bool check = true;
 | 
			
		||||
    typedef checked_int64<check> numeral;
 | 
			
		||||
    typedef vector<numeral> num_vector;
 | 
			
		||||
private:
 | 
			
		||||
    static checked_int64<check> to_numeral(rational const& r) {
 | 
			
		||||
        if (!r.is_int64()) {
 | 
			
		||||
            throw checked_int64<check>::overflow_exception();
 | 
			
		||||
        }
 | 
			
		||||
        return checked_int64<check>(r.get_int64());
 | 
			
		||||
    }
 | 
			
		||||
    static rational to_rational(checked_int64<check> const& i) {
 | 
			
		||||
        return rational(i.get_int64(), rational::i64());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    class value_index1;
 | 
			
		||||
    class value_index2;
 | 
			
		||||
    class value_index3;
 | 
			
		||||
    class index;
 | 
			
		||||
    class passive;
 | 
			
		||||
    class passive2;
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +131,7 @@ private:
 | 
			
		|||
    unsigned get_num_vars() const;
 | 
			
		||||
    numeral get_weight(values const & val, num_vector const& ineq) const;
 | 
			
		||||
    bool is_geq(values const& v, values const& w) const;
 | 
			
		||||
    static bool is_abs_geq(numeral const& v, numeral const& w);
 | 
			
		||||
    bool is_abs_geq(numeral const& v, numeral const& w) const;
 | 
			
		||||
    bool is_subsumed(offset_t idx);
 | 
			
		||||
    bool is_subsumed(offset_t i, offset_t j) const;
 | 
			
		||||
    void recycle(offset_t idx);
 | 
			
		||||
| 
						 | 
				
			
			@ -147,16 +166,16 @@ public:
 | 
			
		|||
    // add inequality v*x >= 0
 | 
			
		||||
    // add inequality v*x <= 0
 | 
			
		||||
    // add equality   v*x = 0
 | 
			
		||||
    void add_ge(num_vector const& v);
 | 
			
		||||
    void add_le(num_vector const& v);
 | 
			
		||||
    void add_eq(num_vector const& v);
 | 
			
		||||
    void add_ge(rational_vector const& v);
 | 
			
		||||
    void add_le(rational_vector const& v);
 | 
			
		||||
    void add_eq(rational_vector const& v);
 | 
			
		||||
 | 
			
		||||
    // add inequality v*x >= b
 | 
			
		||||
    // add inequality v*x <= b
 | 
			
		||||
    // add equality   v*x = b
 | 
			
		||||
    void add_ge(num_vector const& v, numeral const& b);
 | 
			
		||||
    void add_le(num_vector const& v, numeral const& b);
 | 
			
		||||
    void add_eq(num_vector const& v, numeral const& b);
 | 
			
		||||
    void add_ge(rational_vector const& v, rational const& b);
 | 
			
		||||
    void add_le(rational_vector const& v, rational const& b);
 | 
			
		||||
    void add_eq(rational_vector const& v, rational const& b);
 | 
			
		||||
 | 
			
		||||
    void set_is_int(unsigned var_index);
 | 
			
		||||
    bool get_is_int(unsigned var_index) const;
 | 
			
		||||
| 
						 | 
				
			
			@ -164,10 +183,10 @@ public:
 | 
			
		|||
    lbool saturate();
 | 
			
		||||
 | 
			
		||||
    unsigned get_basis_size() const { return m_basis.size(); }
 | 
			
		||||
    void get_basis_solution(unsigned i, num_vector& v, bool& is_initial);
 | 
			
		||||
    void get_basis_solution(unsigned i, rational_vector& v, bool& is_initial);
 | 
			
		||||
 | 
			
		||||
    unsigned get_num_ineqs() const { return m_ineqs.size(); }
 | 
			
		||||
    void get_ge(unsigned i, num_vector& v, numeral& b, bool& is_eq);    
 | 
			
		||||
    void get_ge(unsigned i, rational_vector& v, rational& b, bool& is_eq);    
 | 
			
		||||
 | 
			
		||||
    void set_cancel(bool f) { m_cancel = f; }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -660,8 +660,7 @@ namespace realclosure {
 | 
			
		|||
                return; // interval was already saved.
 | 
			
		||||
            to_restore.push_back(v);
 | 
			
		||||
            inc_ref(v);
 | 
			
		||||
	    void * mem = allocator().allocate(sizeof(mpbqi));
 | 
			
		||||
            v->m_old_interval = new (mem) mpbqi();
 | 
			
		||||
            v->m_old_interval = new (allocator()) mpbqi();
 | 
			
		||||
            set_interval(*(v->m_old_interval), v->m_interval);
 | 
			
		||||
        }
 | 
			
		||||
        void save_interval(value * v) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1237,8 +1236,7 @@ namespace realclosure {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        sign_condition * mk_sign_condition(unsigned qidx, int sign, sign_condition * prev_sc) {
 | 
			
		||||
	    void * mem = allocator().allocate(sizeof(sign_condition));
 | 
			
		||||
            return new (mem) sign_condition(qidx, sign, prev_sc);
 | 
			
		||||
            return new (allocator()) sign_condition(qidx, sign, prev_sc);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
| 
						 | 
				
			
			@ -1246,7 +1244,7 @@ namespace realclosure {
 | 
			
		|||
           This method does not set the interval. It remains (-oo, oo)
 | 
			
		||||
        */
 | 
			
		||||
        rational_function_value * mk_rational_function_value_core(extension * ext, unsigned num_sz, value * const * num, unsigned den_sz, value * const * den) {
 | 
			
		||||
            rational_function_value * r = alloc(rational_function_value, ext);
 | 
			
		||||
            rational_function_value * r = new (allocator()) rational_function_value(ext);
 | 
			
		||||
            inc_ref(ext);
 | 
			
		||||
            set_p(r->num(), num_sz, num);
 | 
			
		||||
            if (ext->is_algebraic()) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1283,7 +1281,7 @@ namespace realclosure {
 | 
			
		|||
        */
 | 
			
		||||
        void mk_infinitesimal(symbol const & n, symbol const & pp_n, numeral & r) {
 | 
			
		||||
            unsigned idx = next_infinitesimal_idx();
 | 
			
		||||
            infinitesimal * eps = alloc(infinitesimal, idx, n, pp_n);
 | 
			
		||||
            infinitesimal * eps = new (allocator()) infinitesimal(idx, n, pp_n);
 | 
			
		||||
            m_extensions[extension::INFINITESIMAL].push_back(eps);
 | 
			
		||||
 | 
			
		||||
            set_lower(eps->interval(), mpbq(0));
 | 
			
		||||
| 
						 | 
				
			
			@ -1335,7 +1333,7 @@ namespace realclosure {
 | 
			
		|||
 | 
			
		||||
        void mk_transcendental(symbol const & n, symbol const & pp_n, mk_interval & proc, numeral & r) {
 | 
			
		||||
            unsigned idx = next_transcendental_idx();
 | 
			
		||||
            transcendental * t = alloc(transcendental, idx, n, pp_n, proc);
 | 
			
		||||
            transcendental * t = new (allocator()) transcendental(idx, n, pp_n, proc);
 | 
			
		||||
            m_extensions[extension::TRANSCENDENTAL].push_back(t);
 | 
			
		||||
            
 | 
			
		||||
            while (contains_zero(t->interval())) {
 | 
			
		||||
| 
						 | 
				
			
			@ -1798,8 +1796,7 @@ namespace realclosure {
 | 
			
		|||
           M and scs will be empty after this operation.
 | 
			
		||||
        */
 | 
			
		||||
        sign_det * mk_sign_det(mpz_matrix & M_s, scoped_polynomial_seq const & prs, int_buffer const & taqrs, scoped_polynomial_seq const & qs, scoped_sign_conditions & scs) {
 | 
			
		||||
	    void * mem = allocator().allocate(sizeof(sign_det));
 | 
			
		||||
            sign_det * r = new (mem) sign_det();
 | 
			
		||||
            sign_det * r = new (allocator()) sign_det();
 | 
			
		||||
            r->M_s.swap(M_s);
 | 
			
		||||
            set_array_p(r->m_prs, prs);
 | 
			
		||||
            r->m_taqrs.set(allocator(), taqrs.size(), taqrs.c_ptr());
 | 
			
		||||
| 
						 | 
				
			
			@ -1814,8 +1811,7 @@ namespace realclosure {
 | 
			
		|||
         */
 | 
			
		||||
        algebraic * mk_algebraic(unsigned p_sz, value * const * p, mpbqi const & interval, mpbqi const & iso_interval, sign_det * sd, unsigned sc_idx) {
 | 
			
		||||
            unsigned idx = next_algebraic_idx();
 | 
			
		||||
	    void * mem = allocator().allocate(sizeof(algebraic));
 | 
			
		||||
            algebraic * r = new (mem) algebraic(idx);
 | 
			
		||||
            algebraic * r = new (allocator()) algebraic(idx);
 | 
			
		||||
            m_extensions[extension::ALGEBRAIC].push_back(r);
 | 
			
		||||
            
 | 
			
		||||
            set_p(r->m_p, p_sz, p);
 | 
			
		||||
| 
						 | 
				
			
			@ -2561,8 +2557,7 @@ namespace realclosure {
 | 
			
		|||
        }
 | 
			
		||||
 | 
			
		||||
        rational_value * mk_rational() {
 | 
			
		||||
	    void * mem = allocator().allocate(sizeof(rational_value));
 | 
			
		||||
            return new (mem) rational_value();
 | 
			
		||||
            return new (allocator()) rational_value();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -85,7 +85,6 @@ namespace subpaving {
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    class context_mpf_wrapper : public context_wrapper<context_mpf> {
 | 
			
		||||
        f2n<mpf_manager> &            m_fm;
 | 
			
		||||
        unsynch_mpq_manager &         m_qm;
 | 
			
		||||
        scoped_mpf                    m_c;
 | 
			
		||||
        scoped_mpf_vector             m_as;
 | 
			
		||||
| 
						 | 
				
			
			@ -103,7 +102,6 @@ namespace subpaving {
 | 
			
		|||
    public:
 | 
			
		||||
        context_mpf_wrapper(f2n<mpf_manager> & fm, params_ref const & p, small_object_allocator * a):
 | 
			
		||||
            context_wrapper<context_mpf>(fm, p, a),
 | 
			
		||||
            m_fm(fm),
 | 
			
		||||
            m_qm(fm.m().mpq_manager()),
 | 
			
		||||
            m_c(fm.m()),
 | 
			
		||||
            m_as(fm.m()),
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +143,6 @@ namespace subpaving {
 | 
			
		|||
    };
 | 
			
		||||
 | 
			
		||||
    class context_hwf_wrapper : public context_wrapper<context_hwf> {
 | 
			
		||||
        f2n<hwf_manager> &            m_fm;
 | 
			
		||||
        unsynch_mpq_manager &         m_qm;
 | 
			
		||||
        hwf                           m_c;
 | 
			
		||||
        svector<hwf>                  m_as;
 | 
			
		||||
| 
						 | 
				
			
			@ -166,7 +163,6 @@ namespace subpaving {
 | 
			
		|||
    public:
 | 
			
		||||
        context_hwf_wrapper(f2n<hwf_manager> & fm, unsynch_mpq_manager & qm, params_ref const & p, small_object_allocator * a):
 | 
			
		||||
            context_wrapper<context_hwf>(fm, p, a),
 | 
			
		||||
            m_fm(fm),
 | 
			
		||||
            m_qm(qm) {
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -80,3 +80,8 @@ void model_v2_pp(std::ostream & out, model_core const & md, bool partial) {
 | 
			
		|||
    display_constants(out, md);
 | 
			
		||||
    display_functions(out, md, partial);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// debugging support
 | 
			
		||||
void pp(model_core const & md) {
 | 
			
		||||
    model_v2_pp(std::cout, md, false);
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										12
									
								
								src/muz/README
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/muz/README
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,12 @@
 | 
			
		|||
muZ: routines related to solving satisfiability of Horn clauses and 
 | 
			
		||||
solving Datalog programs.
 | 
			
		||||
 | 
			
		||||
- base - contains base routines and the main context for
 | 
			
		||||
         maintaining fixedpoint solvers
 | 
			
		||||
- transforms - common rule transformations
 | 
			
		||||
- rel - relational algebra based Datalog engine
 | 
			
		||||
- pdr - PDR based Horn clause solver
 | 
			
		||||
- clp - Dart/Symbolic execution-based solver
 | 
			
		||||
- tab - Tabulation based solver
 | 
			
		||||
- bmc - Bounded model checking based solver
 | 
			
		||||
- fp  - main exported routines
 | 
			
		||||
							
								
								
									
										297
									
								
								src/muz/base/dl_boogie_proof.cpp
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										297
									
								
								src/muz/base/dl_boogie_proof.cpp
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,297 @@
 | 
			
		|||
/**
 | 
			
		||||
 | 
			
		||||
Example from Boogie:
 | 
			
		||||
 | 
			
		||||
(derivation
 | 
			
		||||
(step s!4 (main_loop_LoopHead true true)
 | 
			
		||||
 rule!3  (subst
 | 
			
		||||
    (= assertsPassed@@1 true)
 | 
			
		||||
    (= assertsPassed@2@@0 true)
 | 
			
		||||
    (= main_loop_LoopHead_assertsPassed true)
 | 
			
		||||
  )
 | 
			
		||||
  (labels @950 +895 +668 +670 +893 +899  )
 | 
			
		||||
  (ref  true  ))
 | 
			
		||||
(step s!3 (main true false)
 | 
			
		||||
 rule!1  (subst
 | 
			
		||||
    (= assertsPassed true)
 | 
			
		||||
    (= assertsPassed@0 true)
 | 
			
		||||
    (= assertsPassed@2 false)
 | 
			
		||||
    (= main_assertsPassed false)
 | 
			
		||||
  )
 | 
			
		||||
  (labels @839 +763 +547 +546 +761 +544 +545 +si_fcall_805 +681 +768  )
 | 
			
		||||
  (ref  s!4  ))
 | 
			
		||||
(step s!2 (main_SeqInstr true false)
 | 
			
		||||
 rule!2  (subst
 | 
			
		||||
    (= assertsPassed@@0 true)
 | 
			
		||||
    (= assertsPassed@0@@0 false)
 | 
			
		||||
    (= main_SeqInstr_assertsPassed false)
 | 
			
		||||
  )
 | 
			
		||||
  (labels @890 +851 +572 +si_fcall_883 +853  )
 | 
			
		||||
  (ref  s!3  ))
 | 
			
		||||
(step s!1 (@Fail!0)
 | 
			
		||||
 rule!4  (subst
 | 
			
		||||
    (= assertsPassed@@2 true)
 | 
			
		||||
    (= main_SeqInstr_assertsPassed@@0 false)
 | 
			
		||||
  )
 | 
			
		||||
  (labels  )
 | 
			
		||||
  (ref  s!2  ))
 | 
			
		||||
)
 | 
			
		||||
(model
 | 
			
		||||
"tickleBool -> {
 | 
			
		||||
  true -> true
 | 
			
		||||
  false -> true
 | 
			
		||||
  else -> true
 | 
			
		||||
}
 | 
			
		||||
")
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "dl_boogie_proof.h"
 | 
			
		||||
#include "model_pp.h"
 | 
			
		||||
#include "proof_utils.h"
 | 
			
		||||
#include "ast_pp.h"
 | 
			
		||||
#include "qe_util.h"
 | 
			
		||||
 | 
			
		||||
namespace datalog {
 | 
			
		||||
    
 | 
			
		||||
    /**
 | 
			
		||||
       \brief push hyper-resolution steps upwards such that every use of
 | 
			
		||||
       hyper-resolution uses a premise that is not derived from hyper-resolution.
 | 
			
		||||
              
 | 
			
		||||
       perform the following rewrite:
 | 
			
		||||
       
 | 
			
		||||
       hr(hr(p1,p2,p3,..),p4,p5) => hr(p1,hr(p2,p4),p3,..,p5)
 | 
			
		||||
      
 | 
			
		||||
    */
 | 
			
		||||
 | 
			
		||||
    void mk_input_resolution(proof_ref& pr) {
 | 
			
		||||
        ast_manager& m = pr.get_manager();
 | 
			
		||||
        proof_ref pr1(m);
 | 
			
		||||
        proof_ref_vector premises1(m), premises2(m), premises(m);
 | 
			
		||||
        expr_ref conclusion1(m), conclusion2(m), conclusion(m);
 | 
			
		||||
        svector<std::pair<unsigned, unsigned> > positions1, positions2, positions;
 | 
			
		||||
        vector<expr_ref_vector> substs1, substs2, substs;
 | 
			
		||||
        
 | 
			
		||||
        if (m.is_hyper_resolve(pr, premises1, conclusion1, positions1, substs1) &&
 | 
			
		||||
            m.is_hyper_resolve(premises1[0].get(), premises, conclusion2, positions, substs2)) {
 | 
			
		||||
            for (unsigned i = 1; i < premises1.size(); ++i) {
 | 
			
		||||
                pr1 = premises1[i].get();
 | 
			
		||||
                mk_input_resolution(pr1);
 | 
			
		||||
                premises1[i] = pr1;
 | 
			
		||||
            }
 | 
			
		||||
            for (unsigned i = 0; i < premises.size(); ++i) {
 | 
			
		||||
                pr1 = premises[i].get();
 | 
			
		||||
                mk_input_resolution(pr1);
 | 
			
		||||
                premises[i] = pr1;
 | 
			
		||||
            }
 | 
			
		||||
            unsigned sz = premises.size();
 | 
			
		||||
            for (unsigned i = 1; i < sz; ++i) {
 | 
			
		||||
                proof* premise = premises[i].get();
 | 
			
		||||
                expr_ref_vector literals(m);
 | 
			
		||||
                expr* l1, *l2;
 | 
			
		||||
                if (!m.is_implies(premise, l1, l2)) {
 | 
			
		||||
                    continue;
 | 
			
		||||
                }
 | 
			
		||||
                qe::flatten_and(l1, literals);
 | 
			
		||||
                positions2.reset();
 | 
			
		||||
                premises2.reset();
 | 
			
		||||
                premises2.push_back(premise);       
 | 
			
		||||
                substs2.reset();
 | 
			
		||||
                for (unsigned j = 0; j < literals.size(); ++j) {
 | 
			
		||||
                    expr* lit = literals[j].get();
 | 
			
		||||
                    for (unsigned k = 1; k < premises1.size(); ++k) {
 | 
			
		||||
                        if (m.get_fact(premises1[k].get()) == lit) {
 | 
			
		||||
                            premises2.push_back(premises1[k].get());
 | 
			
		||||
                            positions2.push_back(std::make_pair(j+1,0));
 | 
			
		||||
                            substs2.push_back(expr_ref_vector(m));
 | 
			
		||||
                            break;
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
                premises[i] = m.mk_hyper_resolve(premises2.size(), premises2.c_ptr(), l2, positions2, substs2);
 | 
			
		||||
            }        
 | 
			
		||||
            conclusion = conclusion1;
 | 
			
		||||
            pr = m.mk_hyper_resolve(premises.size(), premises.c_ptr(), conclusion, positions, substs);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void boogie_proof::set_proof(proof* p) {
 | 
			
		||||
        std::cout << "set proof\n";
 | 
			
		||||
        m_proof = p;
 | 
			
		||||
        proof_utils::push_instantiations_up(m_proof);
 | 
			
		||||
        mk_input_resolution(m_proof);
 | 
			
		||||
        std::cout << "proof set\n";
 | 
			
		||||
    }
 | 
			
		||||
        
 | 
			
		||||
    void boogie_proof::set_model(model* m) {
 | 
			
		||||
        m_model = m;
 | 
			
		||||
    }
 | 
			
		||||
    
 | 
			
		||||
    void boogie_proof::pp(std::ostream& out) {
 | 
			
		||||
        if (m_proof) {
 | 
			
		||||
            pp_proof(out);
 | 
			
		||||
        }
 | 
			
		||||
        if (m_model) {
 | 
			
		||||
            model_pp(out, *m_model);
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void boogie_proof::pp_proof(std::ostream& out) {
 | 
			
		||||
        vector<step> steps;
 | 
			
		||||
        ptr_vector<proof> rules;
 | 
			
		||||
        rules.push_back(m_proof);
 | 
			
		||||
        steps.push_back(step());
 | 
			
		||||
        obj_map<proof, unsigned> index;
 | 
			
		||||
        index.insert(m_proof, 0);
 | 
			
		||||
		
 | 
			
		||||
        for (unsigned j = 0; j < rules.size(); ++j) {
 | 
			
		||||
            proof* p = rules[j];
 | 
			
		||||
            proof_ref_vector premises(m);
 | 
			
		||||
            expr_ref conclusion(m);
 | 
			
		||||
            svector<std::pair<unsigned, unsigned> >  positions;
 | 
			
		||||
            vector<expr_ref_vector> substs;
 | 
			
		||||
 | 
			
		||||
            expr* tmp;
 | 
			
		||||
            steps[j].m_fact = m.get_fact(p);
 | 
			
		||||
            m.is_implies(steps[j].m_fact, tmp, steps[j].m_fact);
 | 
			
		||||
            get_subst(p, steps[j].m_subst);
 | 
			
		||||
            get_labels(p, steps[j].m_labels);
 | 
			
		||||
 | 
			
		||||
            if (m.is_hyper_resolve(p, premises, conclusion, positions, substs)) {
 | 
			
		||||
                for (unsigned i = 1; i < premises.size(); ++i) {
 | 
			
		||||
                    proof* premise = premises[i].get();
 | 
			
		||||
                    unsigned position = 0;
 | 
			
		||||
                    if (!index.find(premise, position)) {
 | 
			
		||||
                        position = rules.size();
 | 
			
		||||
                        rules.push_back(premise);
 | 
			
		||||
                        steps.push_back(step());
 | 
			
		||||
                        index.insert(premise, position);
 | 
			
		||||
                    }   
 | 
			
		||||
                    steps[j].m_refs.push_back(position);
 | 
			
		||||
                }
 | 
			
		||||
                get_rule_name(premises[0].get(), steps[j].m_rule_name);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        for (unsigned j = steps.size(); j > 0; ) {
 | 
			
		||||
            --j;
 | 
			
		||||
            step &s = steps[j];
 | 
			
		||||
 | 
			
		||||
            // TBD
 | 
			
		||||
            // s.m_labels;
 | 
			
		||||
 | 
			
		||||
            // set references, compensate for reverse ordering.
 | 
			
		||||
            for (unsigned i = 0; i < s.m_refs.size(); ++i) {
 | 
			
		||||
                s.m_refs[i] = rules.size()-1-s.m_refs[i];
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        steps.reverse();
 | 
			
		||||
        pp_steps(out, steps);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
       \brief extract the instantiation by searching for the first occurrence of a hyper-resolution
 | 
			
		||||
       rule that produces an instance.
 | 
			
		||||
     */
 | 
			
		||||
    void boogie_proof::get_subst(proof* p, subst& s) {
 | 
			
		||||
        ptr_vector<proof> todo;
 | 
			
		||||
        todo.push_back(p);
 | 
			
		||||
        ast_mark visited;
 | 
			
		||||
        std::cout << "get_subst\n" << mk_pp(p, m) << "\n";
 | 
			
		||||
        while (!todo.empty()) {
 | 
			
		||||
            proof* p = todo.back();
 | 
			
		||||
            todo.pop_back();
 | 
			
		||||
            if (visited.is_marked(p)) {
 | 
			
		||||
                continue;
 | 
			
		||||
            }
 | 
			
		||||
            visited.mark(p, true);
 | 
			
		||||
            proof_ref_vector premises(m);
 | 
			
		||||
            expr_ref conclusion(m);
 | 
			
		||||
            svector<std::pair<unsigned, unsigned> >  positions;
 | 
			
		||||
            vector<expr_ref_vector> substs;
 | 
			
		||||
            if (m.is_hyper_resolve(p, premises, conclusion, positions, substs)) {               
 | 
			
		||||
                expr_ref_vector const& sub = substs[0];
 | 
			
		||||
                if (!sub.empty()) {
 | 
			
		||||
                    quantifier* q = to_quantifier(m.get_fact(premises[0].get()));
 | 
			
		||||
                    unsigned sz = sub.size();
 | 
			
		||||
                    SASSERT(sz == q->get_num_decls());
 | 
			
		||||
                    for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
                        s.push_back(std::make_pair(q->get_decl_name(sz-1-i), sub[i]));
 | 
			
		||||
                    }
 | 
			
		||||
                    return;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            unsigned sz = m.get_num_parents(p);
 | 
			
		||||
            for (unsigned i = 0; i < sz; ++i) {
 | 
			
		||||
                todo.push_back(m.get_parent(p, i));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void boogie_proof::get_rule_name(proof* p, symbol& n) {
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void boogie_proof::get_labels(proof* p, labels& lbls) {
 | 
			
		||||
        
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    void boogie_proof::pp_steps(std::ostream& out, vector<step>& steps) {
 | 
			
		||||
        out << "(derivation\n";
 | 
			
		||||
        for (unsigned i = 0; i < steps.size(); ++i) {
 | 
			
		||||
            pp_step(out, i, steps[i]);
 | 
			
		||||
        }
 | 
			
		||||
        out << ")\n";
 | 
			
		||||
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // step       :: "(" "step" step-name fact rule-name subst labels premises ")"
 | 
			
		||||
    void boogie_proof::pp_step(std::ostream& out, unsigned id, step& s) {
 | 
			
		||||
        out << "(step\n";
 | 
			
		||||
        out << " s!" << id << " "; 
 | 
			
		||||
        pp_fact(out, s.m_fact);
 | 
			
		||||
        out << " " << s.m_rule_name << "\n";
 | 
			
		||||
        pp_subst(out << " ", s.m_subst);
 | 
			
		||||
        pp_labels(out << " ", s.m_labels);
 | 
			
		||||
        pp_premises(out << " ", s.m_refs);
 | 
			
		||||
        out << ")\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // fact       :: "(" predicate theory-term* ")"
 | 
			
		||||
    void boogie_proof::pp_fact(std::ostream& out, expr* fact) {
 | 
			
		||||
        out << mk_pp(fact, m) << "\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // subst      :: "(" "subst" assignment* ")"
 | 
			
		||||
    void boogie_proof::pp_subst(std::ostream& out, subst& s) {
 | 
			
		||||
        out << "(subst";
 | 
			
		||||
        for (unsigned i = 0; i < s.size(); ++i) {
 | 
			
		||||
            pp_assignment(out, s[i].first, s[i].second);
 | 
			
		||||
        }
 | 
			
		||||
        out << ")\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // assignment :: "(" "=" variable theory-term ")"
 | 
			
		||||
    void boogie_proof::pp_assignment(std::ostream& out, symbol const& v, expr* t) {
 | 
			
		||||
        out << "\n  (= " << v << " " << mk_pp(t, m) << ")";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    // labels     :: "(" "labels" label* ")"
 | 
			
		||||
    void boogie_proof::pp_labels(std::ostream& out, labels& lbls) {
 | 
			
		||||
        out << "(labels";
 | 
			
		||||
        for (unsigned i = 0; i < lbls.size(); ++i) {
 | 
			
		||||
            out << " " << lbls[i];
 | 
			
		||||
        }
 | 
			
		||||
        out << ")\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // premises "(" "ref" step-name* ")"
 | 
			
		||||
    void boogie_proof::pp_premises(std::ostream& out, refs& refs) {
 | 
			
		||||
        out << "(ref";
 | 
			
		||||
        for (unsigned i = 0; i < refs.size(); ++i) {
 | 
			
		||||
            out << " s!" << refs[i];
 | 
			
		||||
        }
 | 
			
		||||
        out << ")\n";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										87
									
								
								src/muz/base/dl_boogie_proof.h
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/muz/base/dl_boogie_proof.h
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,87 @@
 | 
			
		|||
/**
 | 
			
		||||
 | 
			
		||||
output     :: derivation model
 | 
			
		||||
 | 
			
		||||
derivation :: "(" "derivation" step* ")"
 | 
			
		||||
 | 
			
		||||
step       :: "(" "step" step-name fact rule-name subst labels premises ")"
 | 
			
		||||
 | 
			
		||||
step-name  :: identifier
 | 
			
		||||
 | 
			
		||||
rule-name  :: identifier
 | 
			
		||||
 | 
			
		||||
fact       :: "(" predicate theory-term* ")"
 | 
			
		||||
 | 
			
		||||
subst      :: "(" "subst" assignment* ")"
 | 
			
		||||
 | 
			
		||||
assignment :: "(" "=" variable theory-term ")"
 | 
			
		||||
 | 
			
		||||
labels     :: "(" "labels" label* ")"
 | 
			
		||||
 | 
			
		||||
premises   :: "(" "ref" step-name* ")"
 | 
			
		||||
 | 
			
		||||
model      :: "(" "model" smtlib2-model ")"
 | 
			
		||||
 | 
			
		||||
In each step the "fact" is derivable by hyper-resolution from the named 
 | 
			
		||||
premises and the named rule, under the given substitution for the 
 | 
			
		||||
universally quantified variables in the rule. The premises of each 
 | 
			
		||||
step must have occurred previously in the step sequence. The last fact 
 | 
			
		||||
is a nullary placeholder predicate representing satisfaction of the query 
 | 
			
		||||
(its name is arbitrary).
 | 
			
		||||
 | 
			
		||||
The labels list consists of all the positively labeled sub-formulas whose 
 | 
			
		||||
truth is used in the proof, and all the negatively labeled formulas whose 
 | 
			
		||||
negation is used. A theory-term is a ground term using only interpreted 
 | 
			
		||||
constants of the background theories.
 | 
			
		||||
 | 
			
		||||
The smtlib2-model gives an interpretation of the uninterpreted constants 
 | 
			
		||||
in the background theory under which the derivation is valid. Currently 
 | 
			
		||||
it is a quoted string in the old z3 model format, for compatibility with 
 | 
			
		||||
Boogie, however, this should be changed to the new model format (using 
 | 
			
		||||
define-fun) when Boogie supports this.
 | 
			
		||||
 | 
			
		||||
*/
 | 
			
		||||
 | 
			
		||||
#include "ast.h"
 | 
			
		||||
#include "model.h"
 | 
			
		||||
 | 
			
		||||
namespace datalog {
 | 
			
		||||
    class boogie_proof {
 | 
			
		||||
        typedef vector<std::pair<symbol,expr*> > subst;
 | 
			
		||||
        typedef svector<symbol> labels;
 | 
			
		||||
        typedef unsigned_vector  refs;
 | 
			
		||||
        struct step {
 | 
			
		||||
            symbol m_rule_name;
 | 
			
		||||
            expr*  m_fact;
 | 
			
		||||
            subst  m_subst;
 | 
			
		||||
            labels m_labels;
 | 
			
		||||
            refs   m_refs;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        ast_manager& m;
 | 
			
		||||
        proof_ref    m_proof;
 | 
			
		||||
        model_ref    m_model;
 | 
			
		||||
 | 
			
		||||
        void pp_proof(std::ostream& out);
 | 
			
		||||
        void pp_steps(std::ostream& out, vector<step>& steps);
 | 
			
		||||
        void pp_step(std::ostream& out, unsigned i, step& s);
 | 
			
		||||
        void pp_fact(std::ostream& out, expr* fact);
 | 
			
		||||
        void pp_subst(std::ostream& out, subst& s);
 | 
			
		||||
        void pp_assignment(std::ostream& out, symbol const& v, expr* t);
 | 
			
		||||
        void pp_labels(std::ostream& out, labels& lbls);
 | 
			
		||||
        void pp_premises(std::ostream& out, refs& refs);
 | 
			
		||||
 | 
			
		||||
        void get_subst(proof* p, subst& sub);
 | 
			
		||||
        void get_rule_name(proof* p, symbol&);
 | 
			
		||||
        void get_labels(proof* p, labels&);
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        boogie_proof(ast_manager& m): m(m), m_proof(m), m_model(0) {}
 | 
			
		||||
        
 | 
			
		||||
        void set_proof(proof* p);
 | 
			
		||||
        
 | 
			
		||||
        void set_model(model* m);
 | 
			
		||||
 | 
			
		||||
        void pp(std::ostream& out);
 | 
			
		||||
    };
 | 
			
		||||
}
 | 
			
		||||
										
											
												File diff suppressed because it is too large
												Load diff
											
										
									
								
							| 
						 | 
				
			
			@ -28,34 +28,110 @@ Revision History:
 | 
			
		|||
#include"th_rewriter.h"
 | 
			
		||||
#include"str_hashtable.h"
 | 
			
		||||
#include"var_subst.h"
 | 
			
		||||
#include"dl_base.h"
 | 
			
		||||
#include"dl_costs.h"
 | 
			
		||||
#include"dl_decl_plugin.h"
 | 
			
		||||
#include"dl_relation_manager.h"
 | 
			
		||||
#include"dl_rule_set.h"
 | 
			
		||||
#include"pdr_dl_interface.h"
 | 
			
		||||
#include"dl_bmc_engine.h"
 | 
			
		||||
#include"tab_context.h"
 | 
			
		||||
#include"duality_dl_interface.h"
 | 
			
		||||
#include"rel_context.h"
 | 
			
		||||
#include"lbool.h"
 | 
			
		||||
#include"statistics.h"
 | 
			
		||||
#include"params.h"
 | 
			
		||||
#include"trail.h"
 | 
			
		||||
#include"model_converter.h"
 | 
			
		||||
#include"proof_converter.h"
 | 
			
		||||
#include"model2expr.h"
 | 
			
		||||
#include"smt_params.h"
 | 
			
		||||
#include"dl_rule_transformer.h"
 | 
			
		||||
#include"expr_abstract.h"
 | 
			
		||||
#include"expr_functors.h"
 | 
			
		||||
#include"dl_engine_base.h"
 | 
			
		||||
 | 
			
		||||
struct fixedpoint_params;
 | 
			
		||||
 | 
			
		||||
namespace datalog {
 | 
			
		||||
 | 
			
		||||
    class rule_transformer;
 | 
			
		||||
 | 
			
		||||
    enum execution_result {
 | 
			
		||||
        OK,
 | 
			
		||||
        TIMEOUT,
 | 
			
		||||
        MEMOUT,
 | 
			
		||||
        INPUT_ERROR
 | 
			
		||||
        INPUT_ERROR,
 | 
			
		||||
        APPROX,
 | 
			
		||||
        CANCELED
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class relation_manager;
 | 
			
		||||
 | 
			
		||||
    typedef sort * relation_sort;
 | 
			
		||||
    typedef uint64 table_element;
 | 
			
		||||
    typedef svector<table_element> table_fact;
 | 
			
		||||
 | 
			
		||||
    typedef app * relation_element;
 | 
			
		||||
    typedef app_ref relation_element_ref;
 | 
			
		||||
 | 
			
		||||
    class relation_fact : public app_ref_vector {
 | 
			
		||||
    public:
 | 
			
		||||
        class el_proxy {
 | 
			
		||||
            friend class relation_fact;
 | 
			
		||||
 | 
			
		||||
            relation_fact & m_parent;
 | 
			
		||||
            unsigned m_idx;
 | 
			
		||||
 | 
			
		||||
            el_proxy(relation_fact & parent, unsigned idx) : m_parent(parent), m_idx(idx) {}
 | 
			
		||||
        public:
 | 
			
		||||
            operator relation_element() const {
 | 
			
		||||
                return m_parent.get(m_idx);
 | 
			
		||||
            }
 | 
			
		||||
            relation_element operator->() const {
 | 
			
		||||
                return m_parent.get(m_idx);
 | 
			
		||||
            }
 | 
			
		||||
            relation_element operator=(const relation_element & val) const {
 | 
			
		||||
                m_parent.set(m_idx, val);
 | 
			
		||||
                return m_parent.get(m_idx);
 | 
			
		||||
            }
 | 
			
		||||
            relation_element operator=(const el_proxy & val) {
 | 
			
		||||
                m_parent.set(m_idx, val);
 | 
			
		||||
                return m_parent.get(m_idx);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        typedef const relation_element * iterator;
 | 
			
		||||
 | 
			
		||||
        relation_fact(ast_manager & m) : app_ref_vector(m) {}
 | 
			
		||||
        relation_fact(ast_manager & m, unsigned sz) : app_ref_vector(m) { resize(sz); }
 | 
			
		||||
        relation_fact(context & ctx);
 | 
			
		||||
        
 | 
			
		||||
        iterator begin() const { return c_ptr(); }
 | 
			
		||||
        iterator end() const { return c_ptr()+size(); }
 | 
			
		||||
 | 
			
		||||
        relation_element operator[](unsigned i) const { return get(i); }
 | 
			
		||||
        el_proxy operator[](unsigned i) { return el_proxy(*this, i); }
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    // attempt to modularize context code.
 | 
			
		||||
    class rel_context_base : public engine_base {
 | 
			
		||||
    public:
 | 
			
		||||
        rel_context_base(ast_manager& m, char const* name): engine_base(m, name) {}
 | 
			
		||||
        virtual ~rel_context_base() {}
 | 
			
		||||
        virtual relation_manager & get_rmanager() = 0;
 | 
			
		||||
        virtual const relation_manager & get_rmanager() const = 0;
 | 
			
		||||
        virtual relation_base & get_relation(func_decl * pred) = 0;
 | 
			
		||||
        virtual relation_base * try_get_relation(func_decl * pred) const = 0;
 | 
			
		||||
        virtual bool is_empty_relation(func_decl* pred) const = 0;
 | 
			
		||||
        virtual expr_ref try_get_formula(func_decl * pred) const = 0;
 | 
			
		||||
        virtual void display_output_facts(rule_set const& rules, std::ostream & out) const = 0;
 | 
			
		||||
        virtual void display_facts(std::ostream & out) const = 0;
 | 
			
		||||
        virtual void display_profile(std::ostream& out) = 0;
 | 
			
		||||
        virtual void restrict_predicates(func_decl_set const& predicates) = 0;
 | 
			
		||||
        virtual bool result_contains_fact(relation_fact const& f) = 0;
 | 
			
		||||
        virtual void add_fact(func_decl* pred, relation_fact const& fact) = 0;
 | 
			
		||||
        virtual void add_fact(func_decl* pred, table_fact const& fact) = 0;
 | 
			
		||||
        virtual bool has_facts(func_decl * pred) const = 0;
 | 
			
		||||
        virtual void store_relation(func_decl * pred, relation_base * rel) = 0;
 | 
			
		||||
        virtual void inherit_predicate_kind(func_decl* new_pred, func_decl* orig_pred) = 0;
 | 
			
		||||
        virtual void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt, 
 | 
			
		||||
                                                  symbol const * relation_names) = 0;
 | 
			
		||||
        virtual bool output_profile() const = 0;
 | 
			
		||||
        virtual void collect_non_empty_predicates(func_decl_set& preds) = 0;
 | 
			
		||||
        virtual void transform_rules() = 0;
 | 
			
		||||
        virtual bool try_get_size(func_decl* pred, unsigned& rel_sz) const = 0;
 | 
			
		||||
        virtual lbool saturate() = 0;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    class context {
 | 
			
		||||
| 
						 | 
				
			
			@ -78,40 +154,61 @@ namespace datalog {
 | 
			
		|||
        typedef obj_map<const func_decl, svector<symbol> > pred2syms;
 | 
			
		||||
        typedef obj_map<const sort, sort_domain*> sort_domain_map;
 | 
			
		||||
 | 
			
		||||
        class contains_pred : public i_expr_pred {
 | 
			
		||||
            context const& ctx;
 | 
			
		||||
        public:
 | 
			
		||||
            contains_pred(context& ctx): ctx(ctx) {}
 | 
			
		||||
            virtual ~contains_pred() {}
 | 
			
		||||
            
 | 
			
		||||
            virtual bool operator()(expr* e) {
 | 
			
		||||
                return ctx.is_predicate(e);
 | 
			
		||||
            }
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        ast_manager &      m;
 | 
			
		||||
        register_engine_base& m_register_engine;
 | 
			
		||||
        smt_params &       m_fparams;
 | 
			
		||||
        params_ref         m_params_ref;
 | 
			
		||||
        fixedpoint_params  m_params;
 | 
			
		||||
        fixedpoint_params*  m_params;
 | 
			
		||||
        dl_decl_util       m_decl_util;
 | 
			
		||||
        th_rewriter        m_rewriter;
 | 
			
		||||
        var_subst          m_var_subst;
 | 
			
		||||
        rule_manager       m_rule_manager;
 | 
			
		||||
 | 
			
		||||
        unused_vars_eliminator m_elim_unused_vars;
 | 
			
		||||
        expr_abstractor        m_abstractor;
 | 
			
		||||
        contains_pred      m_contains_p;
 | 
			
		||||
        check_pred         m_check_pred;
 | 
			
		||||
        rule_transformer   m_transf;
 | 
			
		||||
        trail_stack<context> m_trail;
 | 
			
		||||
        ast_ref_vector     m_pinned;
 | 
			
		||||
        app_ref_vector     m_vars;
 | 
			
		||||
        svector<symbol>    m_names;
 | 
			
		||||
        sort_domain_map    m_sorts;
 | 
			
		||||
        func_decl_set      m_preds;
 | 
			
		||||
        sym2decl           m_preds_by_name;
 | 
			
		||||
        pred2syms          m_argument_var_names;
 | 
			
		||||
        rule_set           m_rule_set;
 | 
			
		||||
        rule_set           m_transformed_rule_set;
 | 
			
		||||
        unsigned           m_rule_fmls_head;
 | 
			
		||||
        expr_ref_vector    m_rule_fmls;
 | 
			
		||||
        svector<symbol>    m_rule_names;
 | 
			
		||||
        expr_ref_vector    m_background;
 | 
			
		||||
        model_converter_ref m_mc;
 | 
			
		||||
        proof_converter_ref m_pc;
 | 
			
		||||
 | 
			
		||||
        scoped_ptr<pdr::dl_interface>   m_pdr;
 | 
			
		||||
        scoped_ptr<bmc>                 m_bmc;
 | 
			
		||||
        scoped_ptr<rel_context>         m_rel;
 | 
			
		||||
        scoped_ptr<tab>                 m_tab;
 | 
			
		||||
        scoped_ptr<Duality::dl_interface>   m_duality;
 | 
			
		||||
        rel_context_base*               m_rel;
 | 
			
		||||
        scoped_ptr<engine_base>         m_engine;
 | 
			
		||||
 | 
			
		||||
        bool               m_closed;
 | 
			
		||||
        bool               m_saturation_was_run;
 | 
			
		||||
        execution_result   m_last_status;
 | 
			
		||||
        expr_ref           m_last_answer;
 | 
			
		||||
        DL_ENGINE          m_engine;
 | 
			
		||||
        DL_ENGINE          m_engine_type;
 | 
			
		||||
        volatile bool      m_cancel;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        bool is_fact(app * head) const;
 | 
			
		||||
        bool has_sort_domain(relation_sort s) const;
 | 
			
		||||
        sort_domain & get_sort_domain(relation_sort s);
 | 
			
		||||
| 
						 | 
				
			
			@ -121,7 +218,7 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
 | 
			
		||||
    public:
 | 
			
		||||
        context(ast_manager & m, smt_params& fp, params_ref const& p = params_ref());
 | 
			
		||||
        context(ast_manager & m, register_engine_base& re, smt_params& fp, params_ref const& p = params_ref());
 | 
			
		||||
        ~context();
 | 
			
		||||
        void reset();
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -136,31 +233,41 @@ namespace datalog {
 | 
			
		|||
        ast_manager & get_manager() const { return m; }
 | 
			
		||||
        rule_manager & get_rule_manager() { return m_rule_manager; }
 | 
			
		||||
        smt_params & get_fparams() const { return m_fparams; }
 | 
			
		||||
        fixedpoint_params const&  get_params() const { return m_params; }
 | 
			
		||||
        DL_ENGINE get_engine() { configure_engine(); return m_engine; }
 | 
			
		||||
        fixedpoint_params const&  get_params() const { return *m_params; }
 | 
			
		||||
        DL_ENGINE get_engine() { configure_engine(); return m_engine_type; }
 | 
			
		||||
        register_engine_base& get_register_engine() { return m_register_engine; }
 | 
			
		||||
        th_rewriter& get_rewriter() { return m_rewriter; }
 | 
			
		||||
        var_subst & get_var_subst() { return m_var_subst; }
 | 
			
		||||
        dl_decl_util & get_decl_util()  { return m_decl_util; }
 | 
			
		||||
 | 
			
		||||
        bool output_profile() const { return m_params.output_profile(); }
 | 
			
		||||
        bool fix_unbound_vars() const { return m_params.fix_unbound_vars(); }
 | 
			
		||||
        symbol default_table() const { return m_params.default_table(); }
 | 
			
		||||
        symbol default_relation() const { return m_params.default_relation(); } // external_relation_plugin::get_name()); 
 | 
			
		||||
        symbol default_table_checker() const { return m_params.default_table_checker(); }
 | 
			
		||||
        bool default_table_checked() const { return m_params.default_table_checked(); }
 | 
			
		||||
        bool dbg_fpr_nonempty_relation_signature() const { return m_params.dbg_fpr_nonempty_relation_signature(); }
 | 
			
		||||
        unsigned dl_profile_milliseconds_threshold() const { return m_params.profile_timeout_milliseconds(); }
 | 
			
		||||
        bool all_or_nothing_deltas() const { return m_params.all_or_nothing_deltas(); }
 | 
			
		||||
        bool compile_with_widening() const { return m_params.compile_with_widening(); }
 | 
			
		||||
        bool unbound_compressor() const { return m_params.unbound_compressor(); }
 | 
			
		||||
        bool similarity_compressor() const { return m_params.similarity_compressor(); }
 | 
			
		||||
        unsigned similarity_compressor_threshold() const { return m_params.similarity_compressor_threshold(); }
 | 
			
		||||
        unsigned soft_timeout() const { return m_fparams.m_soft_timeout; }
 | 
			
		||||
        unsigned initial_restart_timeout() const { return m_params.initial_restart_timeout(); } 
 | 
			
		||||
        bool generate_explanations() const { return m_params.generate_explanations(); }
 | 
			
		||||
        bool explanations_on_relation_level() const { return m_params.explanations_on_relation_level(); }
 | 
			
		||||
        bool magic_sets_for_queries() const { return m_params.magic_sets_for_queries();  }
 | 
			
		||||
        bool eager_emptiness_checking() const { return m_params.eager_emptiness_checking(); }
 | 
			
		||||
        bool generate_proof_trace() const;
 | 
			
		||||
        bool output_profile() const;
 | 
			
		||||
        bool output_tuples() const;
 | 
			
		||||
        bool use_map_names() const;
 | 
			
		||||
        bool fix_unbound_vars() const;
 | 
			
		||||
        symbol default_table() const;
 | 
			
		||||
        symbol default_relation() const;
 | 
			
		||||
        symbol default_table_checker() const;
 | 
			
		||||
        bool default_table_checked() const;
 | 
			
		||||
        bool dbg_fpr_nonempty_relation_signature() const;
 | 
			
		||||
        unsigned dl_profile_milliseconds_threshold() const;
 | 
			
		||||
        bool all_or_nothing_deltas() const;
 | 
			
		||||
        bool compile_with_widening() const;
 | 
			
		||||
        bool unbound_compressor() const;
 | 
			
		||||
        bool similarity_compressor() const;
 | 
			
		||||
        unsigned similarity_compressor_threshold() const;
 | 
			
		||||
        unsigned soft_timeout() const;
 | 
			
		||||
        unsigned initial_restart_timeout() const;
 | 
			
		||||
        bool generate_explanations() const;
 | 
			
		||||
        bool explanations_on_relation_level() const;
 | 
			
		||||
        bool magic_sets_for_queries() const;
 | 
			
		||||
        bool eager_emptiness_checking() const;
 | 
			
		||||
        bool bit_blast() const;
 | 
			
		||||
        bool karr() const;
 | 
			
		||||
        bool scale() const;
 | 
			
		||||
        bool magic() const;
 | 
			
		||||
        bool quantify_arrays() const;
 | 
			
		||||
        bool instantiate_quantifiers() const;
 | 
			
		||||
 | 
			
		||||
        void register_finite_sort(sort * s, sort_kind k);
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,9 +287,19 @@ namespace datalog {
 | 
			
		|||
           retrieved by the try_get_predicate_decl() function. Auxiliary predicates introduced
 | 
			
		||||
           e.g. by rule transformations do not need to be named.
 | 
			
		||||
         */
 | 
			
		||||
        void register_predicate(func_decl * pred, bool named = true);
 | 
			
		||||
        void register_predicate(func_decl * pred, bool named);
 | 
			
		||||
 | 
			
		||||
        bool is_predicate(func_decl * pred) const;
 | 
			
		||||
        /**
 | 
			
		||||
           Restrict reltaions to set of predicates.
 | 
			
		||||
         */
 | 
			
		||||
        void restrict_predicates(func_decl_set const& preds);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Retrieve predicates
 | 
			
		||||
        */
 | 
			
		||||
        func_decl_set const& get_predicates() const { return m_preds; }
 | 
			
		||||
        bool is_predicate(func_decl* pred) const { return m_preds.contains(pred); }
 | 
			
		||||
        bool is_predicate(expr * e) const { return is_app(e) && is_predicate(to_app(e)->get_decl()); }
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief If a predicate name has a \c func_decl object assigned, return pointer to it;
 | 
			
		||||
| 
						 | 
				
			
			@ -190,8 +307,12 @@ namespace datalog {
 | 
			
		|||
           
 | 
			
		||||
           Not all \c func_decl object used as relation identifiers need to be assigned to their
 | 
			
		||||
           names. Generally, the names coming from the parses are registered here.
 | 
			
		||||
         */
 | 
			
		||||
        func_decl * try_get_predicate_decl(symbol pred_name) const;
 | 
			
		||||
        */
 | 
			
		||||
        func_decl * try_get_predicate_decl(symbol const& pred_name) const {
 | 
			
		||||
            func_decl * res = 0;
 | 
			
		||||
            m_preds_by_name.find(pred_name, res);
 | 
			
		||||
            return res;
 | 
			
		||||
        }        
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Create a fresh head predicate declaration.
 | 
			
		||||
| 
						 | 
				
			
			@ -231,11 +352,9 @@ namespace datalog {
 | 
			
		|||
        void set_predicate_representation(func_decl * pred, unsigned relation_name_cnt, 
 | 
			
		||||
            symbol const *  relation_names);
 | 
			
		||||
 | 
			
		||||
        void set_output_predicate(func_decl * pred);
 | 
			
		||||
        bool is_output_predicate(func_decl * pred);
 | 
			
		||||
        const decl_set & get_output_predicates();
 | 
			
		||||
        void set_output_predicate(func_decl * pred) { m_rule_set.set_output_predicate(pred); }
 | 
			
		||||
 | 
			
		||||
        rule_set const & get_rules() { flush_add_rules(); return m_rule_set; }
 | 
			
		||||
        rule_set & get_rules() { flush_add_rules(); return m_rule_set; }
 | 
			
		||||
 | 
			
		||||
        void get_rules_as_formulas(expr_ref_vector& fmls, svector<symbol>& names);
 | 
			
		||||
        void get_raw_rule_formulas(expr_ref_vector& fmls, svector<symbol>& names);
 | 
			
		||||
| 
						 | 
				
			
			@ -243,9 +362,9 @@ namespace datalog {
 | 
			
		|||
        void add_fact(app * head);
 | 
			
		||||
        void add_fact(func_decl * pred, const relation_fact & fact);
 | 
			
		||||
 | 
			
		||||
        bool has_facts(func_decl * pred) const;
 | 
			
		||||
        
 | 
			
		||||
        void add_rule(rule_ref& r);
 | 
			
		||||
        void add_rules(rule_ref_vector& rs);
 | 
			
		||||
        
 | 
			
		||||
        void assert_expr(expr* e);
 | 
			
		||||
        expr_ref get_background_assertion();
 | 
			
		||||
| 
						 | 
				
			
			@ -316,35 +435,32 @@ namespace datalog {
 | 
			
		|||
        void reopen();
 | 
			
		||||
        void ensure_opened();
 | 
			
		||||
 | 
			
		||||
        void transform_rules(model_converter_ref& mc, proof_converter_ref& pc);
 | 
			
		||||
        void transform_rules(rule_transformer& trans, model_converter_ref& mc, proof_converter_ref& pc);
 | 
			
		||||
        void replace_rules(rule_set & rs);
 | 
			
		||||
        model_converter_ref& get_model_converter() { return m_mc; }
 | 
			
		||||
        void add_model_converter(model_converter* mc) { m_mc = concat(m_mc.get(), mc); }
 | 
			
		||||
        proof_converter_ref& get_proof_converter() { return m_pc; }
 | 
			
		||||
        void add_proof_converter(proof_converter* pc) { m_pc = concat(m_pc.get(), pc); }
 | 
			
		||||
 | 
			
		||||
        void apply_default_transformation(model_converter_ref& mc, proof_converter_ref& pc);
 | 
			
		||||
        void transform_rules(rule_transformer& transf); 
 | 
			
		||||
        void transform_rules(rule_transformer::plugin* plugin);
 | 
			
		||||
        void replace_rules(rule_set const& rs);
 | 
			
		||||
        void record_transformed_rules();
 | 
			
		||||
 | 
			
		||||
        void apply_default_transformation(); 
 | 
			
		||||
 | 
			
		||||
        void collect_params(param_descrs& r);
 | 
			
		||||
        
 | 
			
		||||
        void updt_params(params_ref const& p);
 | 
			
		||||
 | 
			
		||||
        void collect_predicates(decl_set & res);
 | 
			
		||||
        /**
 | 
			
		||||
           \brief Restrict the set of used predicates to \c res.
 | 
			
		||||
 | 
			
		||||
           The function deallocates unsused relations, it does not deal with rules.
 | 
			
		||||
         */
 | 
			
		||||
        void restrict_predicates(const decl_set & res);
 | 
			
		||||
 | 
			
		||||
        void display_rules(std::ostream & out) const {
 | 
			
		||||
            m_rule_set.display(out);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        void display(std::ostream & out) const {
 | 
			
		||||
            display_rules(out);
 | 
			
		||||
            if (m_rel) m_rel->display_facts(out);
 | 
			
		||||
        }
 | 
			
		||||
        void display(std::ostream & out) const;
 | 
			
		||||
 | 
			
		||||
        void display_smt2(unsigned num_queries, expr* const* queries, std::ostream& out);
 | 
			
		||||
 | 
			
		||||
        void display_profile(std::ostream& out) const;
 | 
			
		||||
 | 
			
		||||
        // -----------------------------------
 | 
			
		||||
        //
 | 
			
		||||
        // basic usage methods
 | 
			
		||||
| 
						 | 
				
			
			@ -352,6 +468,7 @@ namespace datalog {
 | 
			
		|||
        // -----------------------------------
 | 
			
		||||
 | 
			
		||||
        void cancel();
 | 
			
		||||
        bool canceled() const { return m_cancel; }
 | 
			
		||||
 | 
			
		||||
        void cleanup();
 | 
			
		||||
        void reset_cancel() { cleanup(); }
 | 
			
		||||
| 
						 | 
				
			
			@ -418,14 +535,14 @@ namespace datalog {
 | 
			
		|||
        /**
 | 
			
		||||
           \brief Display a certificate for reachability and/or unreachability.
 | 
			
		||||
        */
 | 
			
		||||
        bool display_certificate(std::ostream& out);
 | 
			
		||||
        void display_certificate(std::ostream& out);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
           \brief query result if it contains fact.
 | 
			
		||||
         */
 | 
			
		||||
        bool result_contains_fact(relation_fact const& f);
 | 
			
		||||
 | 
			
		||||
        rel_context& get_rel_context() { ensure_rel(); return *m_rel; }
 | 
			
		||||
        rel_context_base* get_rel_context() { ensure_engine(); return m_rel; }
 | 
			
		||||
 | 
			
		||||
    private:
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -437,27 +554,7 @@ namespace datalog {
 | 
			
		|||
 | 
			
		||||
        void flush_add_rules();
 | 
			
		||||
 | 
			
		||||
        void ensure_pdr();
 | 
			
		||||
 | 
			
		||||
        void ensure_bmc();
 | 
			
		||||
 | 
			
		||||
        void ensure_tab();
 | 
			
		||||
 | 
			
		||||
        void ensure_duality();
 | 
			
		||||
 | 
			
		||||
        void ensure_rel();
 | 
			
		||||
 | 
			
		||||
        void new_query();
 | 
			
		||||
 | 
			
		||||
        lbool rel_query(expr* query);
 | 
			
		||||
 | 
			
		||||
        lbool pdr_query(expr* query);
 | 
			
		||||
 | 
			
		||||
        lbool bmc_query(expr* query);
 | 
			
		||||
 | 
			
		||||
        lbool tab_query(expr* query);
 | 
			
		||||
 | 
			
		||||
        lbool duality_query(expr* query);
 | 
			
		||||
        void ensure_engine();
 | 
			
		||||
 | 
			
		||||
        void check_quantifier_free(rule_ref& r);        
 | 
			
		||||
        void check_uninterpreted_free(rule_ref& r);
 | 
			
		||||
Some files were not shown because too many files have changed in this diff Show more
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue